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).
-
@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=8aGhZQkoFbQhappy 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ý.
-
Mới tìm hiểu khẳng định vl
-
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
-
-
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 và @thelonglqd đã giúp mình hiểu được vấn đề.
Cám ơn cả nhà nhiều ợ
-
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ìnhEvent 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. -
@thanhps42 cmt cho xôm thôi. Ko có ý gì nha :))
-
@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
-
@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
-
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
javascript
vàC++
.- 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 trongV8
hoặclibuv
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úcevent-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.- Đoạn mã nguồn
javascript
bạn viết ra sẽ được thực thi tuần tự trongV8
. Nếu có lời gọikhông đồng bộ
thì thực hiện bước 2, khác thì kết thúc. - 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ởilibuv
, mỗi 1 yêu cầu sẽ được đưa vào queue và thực thi lần lượt bên trongThreadpool
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 1callback queue
, và cứ nằm ở đó rồi chuyển sang bước 3. - Event loop luôn kiểm tra 2 nơi là
call stack
vàcallback queue
. Nếu callstack trống thì kiểm tra callback queue, khác rỗng thì đưa vào callstack xử lý. - 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!
- Code
-
@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 ạ?
-
@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.mdSau đó 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 ạ?
-
@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