首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当响应是异步时,如何在Node.js中处理多个同时请求?

当响应是异步时,如何在Node.js中处理多个同时请求?
EN

Stack Overflow用户
提问于 2020-05-05 05:42:22
回答 1查看 585关注 0票数 1

我可以想象有100个请求到达单个Node.js服务器的情况。它们中的每一个都需要一些DB交互,这些交互是使用任务队列或至少使用微任务队列(例如DB驱动程序接口得到验证)实现的一些本机异步代码。

当请求处理程序停止同步时,Node.js如何返回响应?这100个来自描述的请求从api/web客户端连接到哪里会发生什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-05 06:40:18

此特性在OS级别上可用,并被称为异步I/O或非阻塞I/O (Windows也调用/调用它重叠的I/O) (非常有趣)。

在最低级别,在C (C#/Swift)中,操作系统提供一个API来跟踪请求和响应。根据操作系统的不同,有不同的API可用,Node.js使用利布夫在编译时自动选择最佳可用API,但为了了解异步API的工作方式,让我们看看所有平台都可用的API:select()系统调用。

select()函数如下所示:

代码语言:javascript
运行
复制
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, time *timeout);

fd_set数据结构是您感兴趣的文件描述符的集合/列表,您感兴趣的是监视I/O活动的。请记住,在POSIX中,套接字也是文件描述符。使用此API的方式如下:

代码语言:javascript
运行
复制
// Pseudocode:

// Say you just sent a request to a mysql database and also sent a http
// request to google maps. You are waiting for data to come from both.
// Instead of calling `read()` which would block the thread you add
// the sockets to the read set:

add mysql_socket to readfds
add maps_socket to readfds

// Now you have nothing else to do so you are free to wait for network
// I/O. Great, call select:

select(2, &readfds, NULL, NULL, NULL);

// Select is a blocking call. Yes, non-blocking I/O involves calling a
// blocking function. Yes it sounds ironic but the main difference is
// that we are not blocking waiting for each individual I/O activity,
// we are waiting for ALL of them

// At some point select returns. This is where we check which request
// matches the response:

check readfds if mysql_socket is set {
    then call mysql_handler_callback()
}

check readfds if maps_socket is set {
    then call maps_handler_callback()
}

go to beginning of loop

因此,基本上,您的问题的答案是,我们检查一个数据结构,是什么套接字/文件触发了I/O活动,并执行适当的代码。

毫无疑问,您可以很容易地发现如何泛化此代码模式:与手动设置和检查文件描述符不同,您可以将所有挂起的异步请求和回调保存在一个列表或数组中,并在select()之前和之后循环。这实际上就是Node.js (和一般的javascript )所做的。这个回调/文件描述符的列表有时被称为事件队列,它本身不是队列,而是等待执行的东西的集合。

select()函数在末尾还有一个超时参数,可以用来实现setTimeout()setInterval(),在浏览器中处理GUI事件,这样我们就可以在等待I/O时运行代码,因为记住,select是阻塞的--只有在select返回时才能运行其他代码。通过对定时器的仔细管理,我们可以计算出作为超时传递给select的适当值。

fd_set数据结构实际上不是一个链接列表。在较早的实现中,它是位字段。更现代的实现可以改进位字段,只要它符合API。但这在一定程度上解释了为什么会有这么多的异步API,如pollepollkqueue等,它们的创建是为了克服select的局限性。不同的API以不同的方式跟踪文件描述符,一些使用链接列表、一些哈希表、一些满足可伸缩性(能够侦听数万个套接字)和一些满足速度的需求,大多数API都试图做到这两个方面都优于其他API。不管他们使用什么,最终用于存储请求的只是一种数据结构,可以跟踪文件描述符

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61606484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档