yjhjstz / deep-into-node

In-depth understanding of Node.js: Core Ideas and Source Code Analysis
https://jianghua-yjhs-organization.gitbook.io/in-depth-understanding-of-node.js-core-ideas-and/
4.36k stars 624 forks source link

关于uv__io_poll的一些疑问 #8

Closed hyj1991 closed 7 years ago

hyj1991 commented 7 years ago

在uv_run函数中 I/O部分调用的uv__io_poll,这一块libuv做了跨平台 我看的是Mac下的kqueue.c这个文件,然后有一个小小的疑问: nfds = kevent(loop->backend_fd, events, nevents, events, ARRAY_SIZE(events), timeout == -1 ? NULL : &spec); 第一个疑问是: 当有请求到达服务器时,kevent被唤醒,此时如果因为之前的loop耗时较多导致已经有3个请求积压在kqueue中,那么这里的nfds就等于3吗? 也就是说,这种情况下,在当前这次loop中实际上处理了三个已经到达的请求。 第二个疑问是: 如果是的话,那这三个到达的请求的回调处理是按照达到kqueue的顺序被循环执行的么?

hyj1991 commented 7 years ago

顺着您的书籍加上自己的一些源码阅读,看到这边其实有点疑惑 以http服务器为例,假如每一个请求处理句柄都平均花费20ms 那么如果真正的10000个并发,单进程意味着最后的一个请求要最理想也要等待200s才能被处理 即使开启四个cluster的子进程,那么最理想的情况下,也有会每个子进程最后分配到的四个请求要等待50s才能被处理 这样体验因该是相当之差的,那么以前Node号称的支持十万级别的并发,到底是怎么执行出来的,感觉越看底层代码越无法理解哇 是不是我对于这样的网络I/O请求执行逻辑理解有误呢?

yjhjstz commented 7 years ago

Q1: nfds 代表多个准备好的请求。

Q2:

w = loop->watchers[fd];

由该连接的 fd 值决定,具体可以加打印确认下。

Q3: 确实有误 20ms 等待时间并不阻塞在主线程,而是由主线程分发到线程池处理,多路复用,所以不用排队等待200s。

hyj1991 commented 7 years ago

Q1和Q2我又打印了下,大概明白了 Q3中,比如最简单的

http.createServer(function(req, res){
    //这里的同步业务逻辑花费了20ms
}).listen(8080);

这里的处理回调执行js花费的20ms是会阻塞在主线程的吧

yjhjstz commented 7 years ago

比如业务代码是

fs.writeSync(xx);

那么,会阻塞主线程。

hyj1991 commented 7 years ago

thx~我之前思考的陷入了一个误区,明白了