2013-07-10 47 views
10

Trước hết, tôi khởi động cố gắng hiểu Node.Js. Tôi có hai câu hỏi.
Đơn luồng và vòng lặp sự kiện trong Node.js

Đầu Câu hỏi
Từ the article của Felix, nó nói: "chỉ có thể có một callback bắn cùng một lúc. Cho đến khi gọi lại rằng đã hoàn tất thi công, tất cả các callbacks khác phải chờ đợi trong dòng".

Sau đó, hãy xem xét về đoạn mã sau (sao chép từ nodejs trang web chính thức)

var http = require('http'); 
http.createServer(function (req, res) { 
res.writeHead(200, {'Content-Type': 'text/plain'}); 
res.end('Hello World\n'); 
}).listen(8124, "127.0.0.1"); 

Nếu hai yêu cầu của khách hàng được nhận cùng một lúc, nó có nghĩa là công việc sau đây:

  1. yêu cầu http Đầu tiên sự kiện nhận , Đã nhận được sự kiện yêu cầu thứ hai.
  2. Ngay khi nhận được sự kiện đầu tiên, chức năng gọi lại cho sự kiện đầu tiên đang thực thi.
  3. Đồng thời, chức năng gọi lại cho sự kiện thứ hai phải chờ.

Tôi có đúng không? Nếu tôi đúng, cách kiểm soát Node.js nếu có hàng nghìn yêu cầu của khách hàng trong thời gian rất ngắn.

Câu hỏi thứ hai
Thuật ngữ "Vòng lặp sự kiện" chủ yếu được sử dụng trong chủ đề Node.js. Tôi đã hiểu "Event Loop" như sau từ http://www.wisegeek.com/what-is-an-event-loop.htm;

Vòng lặp sự kiện - hoặc vòng lặp chính, là cấu trúc trong các chương trình kiểm soát và gửi các sự kiện sau sự kiện ban đầu.

Sự kiện ban đầu có thể là bất cứ điều gì, bao gồm nhấn một nút trên bàn phím hoặc nhấp vào nút trên chương trình (trong Node.js, tôi cho rằng sự kiện ban đầu là http yêu cầu, truy vấn db hoặc tệp I/O truy cập).

Đây được gọi là vòng lặp, không phải vì vòng kết nối sự kiện và xảy ra liên tục nhưng do vòng lặp chuẩn bị cho sự kiện, kiểm tra sự kiện , gửi sự kiện và lặp lại quá trình này.

Tôi có xung đột về đoạn thứ hai, đặc biệt là cụm từ "lặp lại quá trình này một lần nữa". Tôi chấp nhận rằng mã số http.createServer từ câu hỏi trên hoàn toàn là "vòng lặp sự kiện" bởi vì nó liên tục nghe các sự kiện yêu cầu http.

Nhưng tôi không biết cách xác định mã sau đây cho dù vòng xoay sự kiện hay sự kiện. Nó không lặp lại bất cứ điều gì ngoại trừ chức năng gọi lại được kích hoạt sau khi truy vấn db kết thúc.

database.query("SELECT * FROM table", function(rows) { 
    var result = rows; 
}); 

Hãy để tôi nghe ý kiến ​​và câu trả lời của bạn.

Trả lời

7

Trả lời một, logic của bạn là chính xác: sự kiện thứ hai sẽ đợi.Và sẽ thực hiện như xa như thời gian gọi lại hàng đợi của nó đến.

Đồng thời, hãy nhớ rằng không có thứ như "đồng thời" trong thế giới kỹ thuật. Mọi thứ đều có địa điểm và thời gian rất cụ thể.

Cách node.js quản lý hàng nghìn kết nối là không cần giữ luồng không tải trong khi có một số cuộc gọi cơ sở dữ liệu chặn logic, hoặc một thao tác IO khác đang xử lý (chẳng hạn như luồng). Nó có thể "phục vụ" yêu cầu đầu tiên, có thể tạo thêm callbacks, và tiến hành các cuộc gọi khác.
Vì không có cách nào để chặn việc thực hiện (ngoại trừ vô nghĩa trong khi (đúng) và tương tự), nó trở nên vô cùng hiệu quả trong việc truyền bá các tài nguyên thực sự trên tất cả các logic ứng dụng.

Chủ đề - tốn kém và khả năng máy chủ của chủ đề có liên quan trực tiếp đến Bộ nhớ khả dụng. Vì vậy, hầu hết các ứng dụng web cổ điển sẽ chỉ bị ảnh hưởng bởi vì RAM được sử dụng trên các luồng chỉ đơn giản là chạy không tải trong khi có khối truy vấn cơ sở dữ liệu đang diễn ra hoặc tương tự. Trong nút đó không phải là một trường hợp.

Tuy nhiên, nó cho phép tạo nhiều luồng (như child_process) qua cluster, giúp mở rộng nhiều khả năng hơn.

Trả lời hai. Không có thứ như "vòng lặp" mà bạn có thể nghĩ đến. Sẽ không có vòng lặp đằng sau hậu trường kiểm tra nếu có kết nối hoặc bất kỳ dữ liệu nào nhận được và vân vân. Ngày nay nó cũng được xử lý bởi các phương thức Async.

Vì vậy, từ quan điểm ứng dụng, không có 'vòng lặp chính' và mọi thứ từ quan điểm của nhà phát triển là sự kiện điều khiển (không phải vòng lặp sự kiện).

Trong trường hợp với http.createServer, bạn ràng buộc gọi lại làm phản hồi yêu cầu. Tất cả các hoạt động ổ cắm và công cụ IO sẽ xảy ra phía sau hậu trường, cũng như bắt tay HTTP, phân tích cú pháp tiêu đề, truy vấn, thông số, v.v. Một khi nó xảy ra đằng sau hậu trường và công việc được thực hiện, nó sẽ giữ dữ liệu và sẽ đẩy gọi lại đến vòng lặp sự kiện với một số dữ liệu. Một khi vòng lặp sự kiện không có vấn đề gì và sẽ đến lúc nó sẽ thực thi trong ngữ cảnh ứng dụng node.js gọi lại của bạn với dữ liệu từ phía sau hậu trường.

Với yêu cầu cơ sở dữ liệu - cùng một câu chuyện. Nó bệnh chuẩn bị và yêu cầu công cụ (có thể làm điều đó thậm chí không đồng bộ một lần nữa), và sau đó sẽ gọi lại khi cơ sở dữ liệu đáp ứng và dữ liệu sẽ được chuẩn bị cho bối cảnh ứng dụng.

Thành thật mà nói, tất cả những gì bạn cần với node.js là hiểu khái niệm, nhưng không thực hiện các sự kiện. Và cách tốt nhất để làm điều đó - thử nghiệm.

+0

điều gì sẽ xảy ra nếu 'createServer' có hoạt động gọi lại (không đồng bộ)? Yêu cầu đầu tiên cho phép nói quá trình một số hoạt động đồng bộ kích hoạt gọi lại và ngay lập tức? Và bắt đầu xử lý yêu cầu hai trong khi gọi lại từ yêu cầu đầu tiên vẫn đang chạy? – Manali

1

1) Có, bạn đã đúng.

Nó hoạt động vì mọi thứ bạn làm với nút chủ yếu là I/O bị ràng buộc.

Khi yêu cầu (sự kiện) mới xuất hiện, nó được đưa vào hàng đợi. Tại thời điểm khởi tạo, Node phân bổ một ThreadPool có trách nhiệm sinh ra các luồng cho xử lý liên kết I/O, như các cuộc gọi mạng/socket, cơ sở dữ liệu, vv (điều này không bị chặn).

Bây giờ, "callbacks" của bạn (hoặc xử lý sự kiện) cực kỳ nhanh vì hầu hết những gì bạn đang làm là rất có thể là CRUD và I/O, không phải CPU.Vì vậy, những callback này cho cảm giác rằng chúng đang được xử lý song song, nhưng chúng thực sự không phải, bởi vì công việc song song thực tế đang được thực hiện thông qua ThreadPool (với đa luồng), trong khi callbacks per-se là chỉ nhận được kết quả từ các luồng này để quá trình xử lý có thể tiếp tục và gửi phản hồi lại cho máy khách.

Bạn có thể dễ dàng xác minh điều này: nếu các cuộc gọi lại của bạn là heavy nhiệm vụ CPU, bạn có thể chắc chắn rằng bạn sẽ không thể xử lý hàng nghìn yêu cầu mỗi giây và nó giảm xuống rất tệ, so với đa luồng hệ thống.

2) Bạn nói đúng, một lần nữa.

Thật không may, do tất cả những trừu tượng này, bạn phải lặn để hiểu những gì đang xảy ra ở chế độ nền. Tuy nhiên, có, có một vòng lặp.

Cụ thể, Nodej được triển khai với libuv.

Thú vị với read.

Nhưng tôi không biết cách xác định mã sau đây cho dù vòng xoay sự kiện hay sự kiện. Nó không lặp lại bất cứ điều gì ngoại trừ chức năng gọi lại được kích hoạt sau khi truy vấn db kết thúc.

Định hướng theo sự kiện là thuật ngữ bạn thường sử dụng khi có vòng lặp sự kiện và ứng dụng được điều khiển bởi các sự kiện như nút nhấp, dữ liệu đến, v.v. Thông thường bạn liên kết một cuộc gọi lại đến các sự kiện như vậy.

Các vấn đề liên quan