事件驱动的编程如何帮助仅使用IO的Web服务器? [英] How does event-driven programming help a webserver that only does IO?

查看:84
本文介绍了事件驱动的编程如何帮助仅使用IO的Web服务器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我们的新后端项目考虑一些框架/编程方法.它考虑了一个BackendForFrontend实现,该实现聚合了下游服务.为简单起见,以下是这些步骤的精简步骤:

I'm considering a few frameworks/programming methods for our new backend project. It regards a BackendForFrontend implementation, which aggregates downstream services. For simplicity, these are the steps it goes trough:

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

与常规"每请求线程处理相比,事件驱动的编程有何优势?一些网站试图进行解释,但通常可以归结为以下内容:

How is event-driven programming better than "regular" thread-per-request handling? Some websites try to explain, and it often comes down to something like this:

第二个解决方案是非阻塞调用.调用者无需等待答案,而是继续执行,但是提供了一个回调,一旦数据到达,该回调将被执行.

The second solution is a non-blocking call. Instead of waiting for the answer, the caller continues execution, but provides a callback that will be executed once data arrives.

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

What I don't understand: we need a thread/handler to await this data, right? Its nice that the event handler can continue, but we still need (in this example) a thread/handler per request that awaits each downstream request, right?

请考虑以下示例:下游请求需要n秒才能返回.在这n秒内,r个请求进入.在每个请求的线程中,我们需要r个线程:每个请求一个.经过n秒后,第一个线程已处理完毕,可用于新请求.

Consider this example: the downstream requests take n seconds to return. In this n seconds, r requests come in. In the thread-per-request we need r threads: one for every request. After n seconds pass, the first thread is done processing and available for a new request.

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

When implementing a event-driven design, we need r+1 threads: an event loop and r handlers. Each handler takes a request, performs it, and calls the callback once done.

那么这如何改善呢?

推荐答案

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

What I don't understand: we need a thread/handler to await this data, right?

并非如此. NIO背后的想法是,永远不会阻塞任何线程.

Not really. The idea behind NIO is that no threads ever get blocked.

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

It is interesting because the operating system already works in a non-blocking way. It is our programming languages that were modeled in a blocking manner.

例如,假设您有一台带有单个CPU的计算机.您执行的任何I/O操作都将比CPU慢几个数量级,对吗?假设您要读取文件.您是否认为CPU会停留在磁盘上,闲置,什么也不做,而磁盘头又会取出一些字节并将其放入磁盘缓冲区中?很明显不是.操作系统将注册一个中断(即回调),并在此期间将有价值的CPU用于其他用途.当磁盘头设法读取了几个字节并使它们可供使用时,将触发中断,然后操作系统将予以关注,恢复先前的处理块并分配一些CPU时间来处理可用数据.

As an example, imagine that you had a computer with a single CPU. Any I/O operation that you do will be orders of magnitude slower than the CPU, right?. Say you want to read a file. Do you think the CPU will stay there, idle, doing nothing while the disk head goes and fetches a few bytes and puts them in the disk buffer? Obviously not. The operating system will register an interruption (i.e. a callback) and will use the valuable CPU for something else in the mean time. When the disk head has managed to read a few bytes and made them available to be consumed, an interruption will be triggered and the OS will then give attention to it, restore the previous process block and allocate some CPU time to handle the available data.

因此,在这种情况下,CPU就像您的应用程序中的线程.它永远不会被阻止.它总是在做一些CPU约束的事情.

So, in this case, the CPU is like a thread in your application. It is never blocked. It is always doing some CPU-bound stuff.

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

The idea behind NIO programming is the same. In the case you're exposing, imagine that your HTTP server has a single thread. When you receive a request from your client you need to make an upstream request (which represents I/O). So what a NIO framework would do here is to issue the request and register a callback for when the response is available.

此后,立即释放您有价值的单线程以处理另一个请求,该请求将注册另一个回调,依此类推,等等.

Immediately after that your valuable single thread is released to attend yet another request, which is going to register another callback, and so on, and so on.

当回调解决后,它将自动安排为由您的单线程处理.

When the callback resolves, it will be automatically scheduled to be processed by your single thread.

因此,该线程用作事件循环,在该循环中,您仅应计划CPU绑定的内容.每次您需要执行I/O时,都是以非阻塞方式完成的,当该I/O完成时,会将一些受CPU约束的回调放入事件循环中以处理响应.

As such, that thread works as an event loop, one in which you're supposed to schedule only CPU bound stuff. Every time you need to do I/O, that's done in a non-blocking way and when that I/O is complete, some CPU-bound callback is put into the event loop to deal with the response.

这是一个强大的概念,因为线程数量很少,您可以处理数千个请求,因此可以更轻松地扩展.事半功倍.

This is a powerful concept, because with a very small amount threads you can process thousands of requests and therefore you can scale more easily. Do more with less.

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

This feature is one of the major selling points of Node.js and the reason why even using a single thread it can be used to develop backend applications.

同样,这就是诸如 Netty 反应流计划 Project Reactor .他们都在寻求促进这种类型的优化和编程模型.

Likewise this is the reason for the proliferation of frameworks like Netty, RxJava, Reactive Streams Initiative and the Project Reactor. They all are seeking to promote this type of optimization and programming model.

还有一个有趣的新框架运动,这些新框架利用了这些强大的功能并试图相互竞争或互补.我说的是有趣的项目,例如 Vert.x Ratpack .而且我很确定还有其他语言可供使用.

There is also an interesting movement of new frameworks that leverage this powerful features and are trying to compete or complement one another. I'm talking of interesting projects like Vert.x and Ratpack. And I'm pretty sure there are many more out there for other languages.

这篇关于事件驱动的编程如何帮助仅使用IO的Web服务器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆