Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
621 views
in Technique[技术] by (71.8m points)

javascript - NodeJS Asychronous I/O Execution

As far as I understand, although there is apparently a 'helper' thread, Node.js runs in a single thread, therefore, each operation in the Event Loop stack runs one after another and other operations and queued while Node performs asynchronous I/O in the background, this way the server is able to perform other actions while doing non-blocking I/O without the need to create wasteful multiple threads, the I/O is finished and the it's associated callback is pulled into the Event Loop queue, and that's the big thing about Node.

However, in many articles I've ready, is not clear if asynchronous I/O operations run in parallel with other I/O operations in I/O a separate thread or process or if each requested I/O operation runs one after another in a helper thread while the Event Loop performs other actions. And after reading the phrase "Everything runs in parallel except your code" this makes me even more confuse.

The question is, multithread or not multithread? If each asynchronous operation runs in a separate thread, doesn't it have use as much resources as an Apache server would?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Node is, essentially, non-multithreaded. The asynchronicity goes deeper than Node, deeper than libuv, and even deeper than the facilities (epoll, kqueue, IOCP, etc.) that libuv uses.

When the kernel gets an async request it does not fire up another thread of execution. Instead, it adds it to a simple list of "things to watch out for." If a process makes a network read request, for instance, the kernel will make an entry on that list. It's something like "hey, next time there is a read request that looks like this, let the process know about it." After making this entry, the kernel returns control back to the process and both go on their merry way. The only thing that survives is the data on the list.

The kernel is informed of a network read event via hardware interrupts. Using an interrupt, the processor yanks the kernel into a special loop -- stopping anything it's doing at the moment -- and tells it about the event. The kernel then checks against its list of outstanding requests, and (in the kevent AIO case) sends a similar interrupt (in the form of a signal) to the process to let it know about the network read. So, no threads. Just interruptions.

Well, this is a bit of a simplification: in the non-AIO kevent and epoll cases, after the kernel gets a network read it'll just put it on an event list. The process periodically checks that event list to see if something came in for it.

Also, from the kernel view, this is how all I/O works. The big difference is that the kernel isn't requiring the process to wait for the kernel to get back to it.

There is actually a little more complexity in libuv as non-network requests (and DNS requests, which are special, painful forms of network requests) are handled by threads. This is because the kernel facilities for making those asynchronous are generally not so great, if they exist at all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...