Vấn đề về event loop


  • Global Moderator

    Mình xin bổ sung thêm 1 chút. Về mã nguồn CORE của nodejs thì bao gồm 2 thành phần chính javascriptC++.

    • Code C++ bao gồm các đoạn mã xử lý native hoặc wrap tới các thư viện bên ngoài và rất quan trọng như V8, libuv, openssl, zlib. Đây là các thành phần tạo nên kiến trúc của NodeJS. Các bạn xem hình bên dưới.
    • Code javascript bao gồm các tiện ích thuần js như util.js hoặc là các đoạn mã binding tới các mã nguồn C++ mà sẽ được thực thi ở bên trong V8 hoặc libuv khi chạy 1 ứng dụng node.

    Về kiến trúc và mô hình hoạt động của nodejs thì nó tuân theo cơ chế Non-blocking và kiến trúc event-loop. Các bạn có thể xem hình vẽ mô hình này để dễ hình dung hơn. Nhưng cơ bản kiến trúc này sẽ được thực thi qua các bước sau.

    1. Đoạn mã nguồn javascript bạn viết ra sẽ được thực thi tuần tự trong V8. Nếu có lời gọi không đồng bộ thì thực hiện bước 2, khác thì kết thúc.
    2. Lời gọi được xử lý bên trong OS hoặc thực thi các Web API. Lời gọi này được quản lý bởi libuv, mỗi 1 yêu cầu sẽ được đưa vào queue và thực thi lần lượt bên trong Threadpool khi pool này rảnh. Size mặc định libuv qui định là 4, các bạn có thể tham khảo thêm ở đây. Kết thúc bước này trả về kết quả đẩy vào 1 callback queue, và cứ nằm ở đó rồi chuyển sang bước 3.
    3. Event loop luôn kiểm tra 2 nơi là call stackcallback queue. Nếu callstack trống thì kiểm tra callback queue, khác rỗng thì đưa vào callstack xử lý.
    4. V8 xử lý (tuần tự) và kết thúc chương trình

    Mời các bác bổ sung thêm!

    Concurrency model and Event Loop



  • @Vũ A ơi. A cho e hỏi tẹo về các module async. Bây h nếu như e muốn viết 1 hàm async thì phải như nào ạ?


  • Global Moderator

    @duynb94 A nghĩ e phải tìm hiểu xem async nó có những khả năng gì ? Cách tiếp cận tốt nhất là đọc tài liệu trên trang chủ của nó. Sau đó tìm 1 ví dụ tương ứng xem nó thực hiện như thế nào.

    Async: http://caolan.github.io/async/
    Có thể xem tài liệu cũ ở đây: https://github.com/caolan/async/blob/v1.5.2/README.md

    Sau đó chạy thử ví dụ này, rồi phân tích nhé

    var async = require('async');
    
    async.waterfall(
        [
            function(callback) {
                callback(null, 'Yes', 'it');
            },
            function(arg1, arg2, callback) {
                var caption = arg1 +' and '+ arg2;
                callback(null, caption);
            },
            function(caption, callback) {
                caption += ' works!';
                callback(null, caption);
            }
        ],
        function (err, caption) {
            console.log(caption);
            // Node.js and JavaScript Rock!
        }
    );
    


  • @Vũ A ơi. A hiểu nhầm ý e hỏi rồi ạ. E muốn hỏi là cách viết 1 hàm chạy asynchronous giống như các module trên github kiểu: setTimeout(), request ... E cũng mới tìm hiểu về Node.js nên thấy cái vấn đề chạy asynchronous nhưng mà lại trên 1 luồng của nó rất hay. Mà e vẫn chưa hiểu rõ được. :((



  • @Vũ async so với promise thì sao bác?



  • @Vũ À mà a ơi. E có thể kết bạn facebook với a để thỉnh thoảng học hỏi a các vấn đề về Node.js được ko ạ?


  • Global Moderator

    @NguyenQuan mình thì vẫn dùng kết hợp 2 thằng này. đôi lúc vẫn phải chuyển sang sử dụng async vì dễ handle hơn :)


  • Global Moderator

    @duynb94 cứ trao đổi trên diễn đàn cho tiện đi e :)



  • @tresdin said in Vấn đề về event loop:

    Sự chậm trễ trong thực thi kết nối thứ 2 trong ví dụ mà bạn đưa ra xuất phát từ việc tác vụ CPU chuyên sâu ở kết nối thứ nhất và tác vụ xử lý kết nối thứ 2 đều được thực thi bởi một luồng (thread) duy nhất. Điều này là hoàn toàn bình thường và hợp lý.

    Mình xin lấy một ví dụ để bạn dễ hiểu hơn.
    Giả sử bạn đang làm việc cho một công ty với tư cách là một developer. Vào một hôm đẹp trời, thay vì thuê thêm nhân viên, sếp của bạn quyết định giao toàn bộ công việc của công ty đó cho bạn. Từ việc quét nhà, dọn dẹp, đến việc viết báo cáo, lập trình hay đi hội thảo. Tất cả các việc do một mình bạn đảm đương. Bạn có cho rằng bạn sẽ hoàn thành toàn bộ công việc đó nhanh như khi bạn chỉ phải làm duy nhất một công việc là lập trình? Câu trả lời chắc chắn sẽ là không. Để đảm bảo về mặt thời gian, việc bạn cần làm là yêu cầu sếp thuê thêm người làm và bố trí lại công việc cho phù hợp.

    Quay lại với ví dụ mà bạn đưa ra, việc tất cả các tác vụ được thực thi bởi một luồng duy nhất rất giống với ví dụ minh họa trên. Trên thực tế, những tác vụ I/O (I/O tasks) hoặc tác vụ CPU chuyên sâu (CPU intensive tasks) thường hoặc nên được thực thi ở một luồng khác. Việc này giúp chúng ta tránh được thời gian phải chờ đợi trong quá trình các tác vụ đó được thực thi. Và khi các tác vụ đó được thực thi trên một luồng khác, chúng ta cũng cần biết khi nào thì các chúng được bắt đầu, được thực thi, hay đã thực thi xong thông qua việc sử dụng Event để gửi tín hiệu thông báo ngược trở lại luồng chính về trạng thái của quá trình thực thi. Quá trình này cứ được lặp đi lặp lại như vậy nên thường được gọi là mô hình Event Loop. Javascript không phải là ngôn ngữ duy nhất áp dụng mô hình này.

    Bên cạnh đó, việc nói Nodejs đơn luồng là không thực sự chính xác. Thực chất, chỉ có đoạn code mà bạn viết ra ở tầng ứng dụng (application layer) là được thực thi đơn luồng. Phía sâu bên trong Nodejs, các tác vụ I/O hay CPU chuyên sâu đa số được thực thi đa luồng, và được viết bằng các ngôn ngữ khác không phải Javascript (C, C++,...).

    Để kết luận, mình muốn khẳng định rằng Event Loop chỉ là một trong những mô hình được thiết kế cho việc quản lý các tác vụ không đồng bộ đòi hỏi nhiều thời gian thực thi thông qua công cụ Event. Nó không phải là một phép màu mang lại sự cải thiện về tốc độ. Cái chính vẫn nằm ở khả năng lập trình, khả năng quản lí và xử lý tác vụ một cách hợp lý của các developer.

    Bác nói hay quá. Em cứ nghĩ là node chạy đơn luồng thì sẽ lãng phí tài nguyên, giờ đọc được thông tin này của bác đúng là được "khai sáng văn minh" :O


Log in to reply