Vấn đề về event loop



  • @ndaidong đã nói trong Vấn đề về event loop:

    @tung có vẻ bạn thanhps42 bị nhầm lẫn giữa "event loop" với vòng lặp (loop/iteration).

    Không bạn ơi, cái vòng lặp là mình làm để ví dụ cho 1 công việc nào đó tốn thời gian. Ý mình là người ta vào 1 route, mà route này phất 15s mới xử lý xong rồi mới trả về kết quả cho người dùng, thì lúc này nodejs đang bận xử lý cái công việc đang dang dở kia nên nó không thể tiếp nhận thêm request của người dùng mới (event mới).

    P/s: có bạn hidemanvn hiểu đúng ý mình đó.



  • @thanhps42 Trong thời gian xử lý 1 tác vụ I/O thì node vẫn nhận thêm các request khác, còn việc xử lý tác vụ I/O đó như thế nào thì sẽ được để trong 1 hàm callback, tác vụ xong, hàm callback sẽ được gọi và thực thi câu lệnh bên trong nó.
    Còn muốn hiểu rõ về event loop, bạn nên xem video này, được recommend khá nhiều trong những tuts về node:
    https://www.youtube.com/watch?v=8aGhZQkoFbQ

    happy coding =))



  • @thanhps42 ok. Nếu vậy thì nó là về sync vs async.

    Ví dụ khi kịch bản đang đọc file bằng readFileSync, nó sẽ không thể xử lý các request khác như trường hợp vòng lặp while của bạn.

    let s = fs.readFileSync('./data.json');
    console.log(s);
    

    Nếu đọc file bằng readFile thì callback sẽ được đẩy vào message queue và lúc này mới là câu chuyện của Event loop. Các request đến vẫn được xử lý bình thường trong khi fs đang đọc nội dung từ drive.

    fs.readFile('./data.json', 'utf8', (err, s) => {
       console.log(s);
    });
    

    Đó là lý do vì sao trong Node.js người ta khuyến khích viết async thay vì sync.

    Trở lại với ví dụ của bạn, tuy các vòng lặp chiếm resource để xử lý nhưng không được cho vào message queue nên hòan toàn không liên quan đến event loop. Khi có các tác vụ chiếm dụng tài nguyên kiểu đó (big data, image processing...) thì cách phổ biến vẫn là ném sang cho 1 thread con xử lý.


  • Global Moderator

    Mới tìm hiểu khẳng định vl

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    0


  • M nghĩ cũng chỉ là chưa biết thôi, cách diễn đạt có thể hơi tự tin quá về kt của m, nhưng nhận được 2 rep có "vl" từ mode và ad chắc sẽ ko quay lại dd lần nữa mất :D



  • @tung đã nói trong Vấn đề về event loop:

    Rikky here:

    Ôi thánh hiển linh!



  • Hoang mang vl, thế ai đúng ai sai?
    các bác chém vừa thôi, biết thì hãy nói không lại hỏng cả 1 thế hệ



  • @Vũ mình có ghi rõ là theo quan điểm của mình mà, và ở dưới mình cũng nói đây là thắc mắc của mình nhờ mọi người giải đáp chứ mình đâu có khẳng định ở chỗ nào đâu.

    Chân thành cám ơn đến @hidemanvn @ndaidong@thelonglqd đã giúp mình hiểu được vấn đề.

    Cám ơn cả nhà nhiều ợ :D



  • 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.


  • Global Moderator

    @thanhps42 cmt cho xôm thôi. Ko có ý gì nha :))

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    0


  • @tresdin cám ơn câu trả lời của bạn nhiều. Câu trả lời chất lượng lắm bạn :D



  • @tresdin đã nói trong Vấn đề về event loop:

    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á

    Great


  • 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

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    6


  • @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!
        }
    );
    

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    0


  • @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 :)

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    0

  • Global Moderator

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

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    0

Log in to reply