当前位置: 首页 > 知识库问答 >
问题:

事件驱动编程如何帮助只执行IO的Web服务器?

公冶龙野
2023-03-14

我正在为我们的新后端项目考虑一些框架/编程方法。它涉及后端forfrontend实现,该实现聚合了下游服务。为简单起见,以下是它所经历的步骤:

  1. 请求进入Web服务器
  2. Web服务器发出下游请求
  3. 下游请求返回结果
  4. Web服务器返回请求

事件驱动编程如何比“常规”按请求处理线程更好?一些网站试图解释,它通常归结为这样的东西:

第二种解决方案是非阻塞调用。调用方没有等待答案,而是继续执行,但提供了一个回调,该回调将在数据到达后执行。

我不明白的是:我们需要一个线程/处理程序来等待这些数据,对吗?事件处理程序可以继续很好,但我们仍然需要(在本例中)每个请求都有一个线程/处理程序,等待每个下游请求,对吗?

考虑这个例子:下游请求需要n秒才能返回。在这n秒内,r个请求进来。在每个请求线程中,我们需要r个线程:每个请求一个。n秒后,第一个线程完成处理并可用于新请求。

在实现事件驱动设计时,我们需要r 1线程:一个事件循环和r处理程序。每个处理程序接受一个请求,执行它,并在完成后调用回调。

那么这是如何改善情况的呢?

共有2个答案

韶浩博
2023-03-14

非阻塞范式的整体思想是通过这种称为“事件循环”的思想实现的

有趣的参考资料:

  1. http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch06lev1sec2.html
史淳
2023-03-14

我不明白的是:我们需要一个线程/处理程序来等待这些数据,对吗?

不是真的。NIO背后的思想是没有线程被阻塞。

这很有趣,因为操作系统已经以非阻塞方式工作了。是我们的编程语言以阻塞方式建模。

例如,假设您有一台只有一个CPU的计算机。您执行的任何输入/输出操作都将比CPU慢几个数量级,对吗?。假设你想读一个文件。你认为当磁头去提取几个字节并将它们放入磁盘缓冲区时,CPU会保持在那里,空闲,什么也不做吗?显然不是。操作系统将注册一个中断(即回调),同时将把有价值的CPU用于其他事情。当磁头已设法读取几个字节并使其可供使用时,将触发中断,然后操作系统将关注它,恢复以前的进程块,并分配一些CPU时间来处理可用数据。

因此,在这种情况下,CPU就像应用程序中的线程。它从不被阻塞。它总是在做一些CPU受限的事情。

NIO编程背后的思想是相同的。在您公开的情况下,假设您的HTTP服务器只有一个线程。当您收到客户的请求时,您需要发出上游请求(表示输入/输出)。因此,NIO框架在这里要做的是发出请求,并在响应可用时注册回调。

紧接着,您有价值的单线程被释放以参与另一个请求,该请求将注册另一个回调,依此类推。

当回调解析时,它将自动安排由单个线程处理。

因此,该线程可以作为一个事件循环,在其中您应该只调度CPU限制的内容。每次需要进行I/O时,都是以非阻塞的方式进行的,当I/O完成时,会将一些CPU限制的回调放入事件循环以处理响应。

这是一个强大的概念,因为使用非常少的线程,您可以处理数千个请求,因此可以更容易地扩展。少花钱多办事。

此功能是Node的主要卖点之一。js以及为什么即使使用单个线程也可以用于开发后端应用程序。

同样,这也是Netty、RxJava、反应流倡议和项目反应器等框架激增的原因。他们都在寻求推广这种优化和编程模型。

还有一个有趣的新框架运动,它们利用了这些强大的功能,并试图相互竞争或补充。我说的是像Vert. x和Ratpack这样有趣的项目。我很确定其他语言还有更多。

 类似资料:
  • 事件源和CQR如何帮助实现微服务的解耦架构。 我们可以让微服务拥有自己的数据,其他人通过服务访问数据,即使是通过传统的持久性手段。不是吗?

  • 问题 你应该已经听过基于事件驱动或异步I/O的包,但是你还不能完全理解它的底层到底是怎样工作的, 或者是如果使用它的话会对你的程序产生什么影响。 解决方案 事件驱动I/O本质上来讲就是将基本I/O操作(比如读和写)转化为你程序需要处理的事件。 例如,当数据在某个socket上被接受后,它会转换成一个 receive 事件,然后被你定义的回调方法或函数来处理。 作为一个可能的起始点,一个事件驱动的框

  • 我用的是linux box。 我无法使用IPv6 FTP服务器执行任何操作。我能够使用IPV6 FTP服务器进行连接。但我什么时候做任何操作(比如ls、get、put…)下面是例外情况(用粗体突出显示)。 [root@SKP-vlnx~]#ftp aa01:9:1::22:56ff:231:4b连接到aa01:9:1::22:56ff:231:4b(aa01:9:1::22:56ff:231:4b

  • 8.3 Tkinter 事件驱动编程 在 8.2 节中我们学习了图形用户界面中的各种构件的用法,至此我们已经能够为应用程 序搭建用户界面的外观部分,用户界面的另一个重要部分是各界面元素所对应的程序功能。 GUI 应用程序与普通应用程序的一个不同之处就在于,实现程序功能的代码与图形界面元素 相关联,这导致了一种新的程序执行模式——事件驱动。8.1.3 中简单介绍了事件驱动编程的 基本概念,现在我们来

  • 在前面的文章中我们简单介绍了事件驱动编程,现在让我们看看真实的代码并介绍EventBus的基础用法。 首先我会参考下图(从EventBus仓库截取的),介绍在事件驱动编程中扮演中心角色的实体们。 事件总线EventBus:连接所有其他实体的中央通信通道; 事件Event:发生的动作,几乎可以是任何事情(应用启动,收到某些数据,用户交互等等); 订阅者Subscriber:订阅者监听事件总线,当总线

  • 虽然在Android开发具有某些事件驱动的特性,但它还远不是纯粹的事件驱动架构。这算是好事还是坏事呢?正如在软件开发领域中任何事情一样,想回答它并不容易:这取决于具体情况。 首先我们来给事件驱动编程下一个定义。事件驱动编程是一种编程范式,程序的执行流程是由动作(actions,例如用户交互,其他线程发送的消息等等)触发的事件(event)决定的。在这个意义上,Android是部分事件驱动:我们都知