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

时间:2018-04-03 14:43:35

标签: multithreading webserver event-driven event-driven-design

我正在为我们的新后端项目考虑一些框架/编程方法。它关注BackendForFrontend实现,它聚合下游服务。为简单起见,这些是它通过的步骤:

  1. 请求进入网络服务器
  2. 网络服务器提出下游请求
  3. 下游请求返回结果
  4. 网络服务器返回请求
  5. 事件驱动编程如何比常规"更好?每个请求处理线程?一些网站试图解释,它经常归结为这样的事情:

      

    第二种解决方案是非阻塞呼叫。调用者不再等待答案,而是继续执行,但提供了一旦数据到达就会执行的回调。

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

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

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

    那么这怎么改善了呢?

2 个答案:

答案 0 :(得分:2)

  

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

不是真的。 NIO背后的想法是没有线程被阻止。

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

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

因此,在这种情况下,CPU就像应用程序中的一个线程。它永远不会被阻止。它总是做一些CPU绑定的东西。

NIO编程背后的想法是一样的。在您公开的情况下,假设您的HTTP服务器有一个单独的线程。当您收到客户端的请求时,您需要发出上游请求(代表I / O)。那么NIO框架在这里要做的是发出请求并在响应可用时注册回调。

在此之后,您的宝贵的单线程被释放以参加另一个请求,该请求将注册另一个回调,依此类推,等等。

当回调结算时,它将自动安排由您的单个线程处理。

因此,该线程作为一个事件循环,你应该只调度CPU绑定的东西。每次需要执行I / O时,都是以非阻塞方式完成的,当I / O完成时,会将一些CPU绑定的回调放入事件循环中以处理响应。

这是一个强大的概念,因为使用非常少量的线程,您可以处理数千个请求,因此您可以更轻松地进行扩展。少做更多。

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

同样,这也是NettyRxJavaReactive Streams InitiativeProject Reactor等框架激增的原因。他们都在寻求推广这种优化和编程模型。

还有一个有趣的新框架运动,利用这些强大的功能,并试图相互竞争或互补。我说的是Vert.xRatpack等有趣的项目。而且我很确定其他语言还有很多其他语言。

答案 1 :(得分:0)