事件驱动模型和反应堆模式之间有什么区别?[关闭]


72

摘自Wikipedia Reactor Pattern文章:

反应堆设计模式是一种事件处理模式,用于处理通过一个或多个输入同时交付给服务处理程序的服务请求。

它命名了几个例子,例如nodejstwistedeventmachine

但是我了解到上面是流行的事件驱动框架,因此使它们也成为反应堆模式框架吗?

如何区分这两者?还是一样?

Answers:


124

反应堆模式比“事件驱动的编程”更为具体。它是进行事件驱动的编程时使用的一种特定的实现技术。但是,该术语在典型的会话中使用的准确性不高,因此您应谨慎使用该术语,并希望您的听众理解您,并且在遇到该术语时应谨慎理解。

一种查看反应堆模式的方法是,将其视为与“非阻塞”操作的思想密切相关。当某些操作可以完成而没有阻塞时,反应堆会发出通知。例如,select(2)可用于实施反应器图案用于读取和使用标准的BSD套接字API的(写入到插座recv(2)send(2)等)。 select会告诉您何时可以立即从套接字接收字节-例如,因为字节存在于该套接字的内核接收器缓冲区中。

考虑这些想法时,您可能要考虑的另一种模式是proactor模式。与反应堆模式相比,前摄器模式不管它们是否可以立即完成都开始操作,使其异步执行,然后安排传递有关其完成的通知。

Windows I / O完成端口(IOCP)API是一个示例,可以看到proactor模式。使用IOCP在套接字上执行发送时,无论内核发送缓冲区中是否有用于该套接字的空间,都会启动发送操作。当WSASend调用立即完成时,发送操作继续(在另一个线程中,也许在内核中的线程中)。当发送实际完成时(仅意味着要发送的字节已复制到该套接字的内核发送缓冲区中),将为调用提供一个回调函数WSASend(在应用程序的新线程中)。

这种启动操作然后在操作完成时得到通知的方法是异步操作概念的核心。将其与非阻塞操作进行比较,在非阻塞操作中,您等待直到操作可以立即完成才尝试执行它。

两种方法均可用于事件驱动的编程。使用反应堆模式,程序等待(例如)套接字可读的事件,然后从中读取。使用proactor模式,该程序改为等待套接字读取完成的事件

严格来说,Twisted滥用反应堆一词。基于select(2)twisted.internet.selectreactor)的双绞反应器是使用非阻塞I / O实现的,它非常类似于反应器。但是,它提供给应用程序代码的接口是异步的,从而使其更加类似于proactor。Twisted还具有基于IOCP的电抗器。该反应器公开相同的面向应用程序的异步API,使用类似于proactor的IOCP API。这种混合方法因平台的不同而有所不同,它使“反应堆”和“执行器”这两个术语都没有特别准确,但是由于公开的APItwisted.internet.reactor基本上是完全异步的,而不是非阻塞的,因此 可能是更好的名字选择。


1
1.我可以这样说吗:Reactor模式是一种异步对事件进行排队,但对它们进行多路分解并同步分配的模式;而Proactor模式排队,解复用并异步分配它们?2.考虑到select(2)API,使用事件进行编程时,诸如libevent之类的现代库为它带来了什么好处(我不知道与该问题相关,但您是该领域的专家。)
霍华德

关于1:维基百科页面就是这样写的,所以我犹豫只说“不” :)但是,作为一名从业人员,这并不是我在现实世界中遇到的措辞。由于这些术语相当晦涩,并且在使用它们时经常被误用,所以我认为您可以放心地说出来,但也可以安全地说别的东西(例如反应堆->非阻塞,proactor->异步)。也许两者之间相距甚远(您可以想象“同步”的意思是“同步,非阻塞”-毕竟,“同步,阻塞”会干扰反应堆的进一步运行)
Jean-Paul Calderone

4
关于2:select(2)的级别很低并且难以使用。对于大量事件源而言,它的效率也不高。现代平台已经超越了它,提供了等效但更有效的API(/ dev / poll,epoll,kqueue等)。libevent(或Twisted)的一个优点是所有这些不同机制的抽象,因此可以将应用程序写入统一的API,同时仍然受益于运行时平台上最有效的API。加上协议实现,高级API的形式来管理asynchronousness等明显的附加功能
让-保罗·Calderone的

1
对于选择(2)对epoll的(4),见比较stackoverflow.com/questions/2032598/...
让保Calderone的

1
如果您从套接字获取select接收字节来解释反应堆模式,那么您应该使用它们来解释proactor模式。否则,这很令人困惑,因为对比变得太模糊了,因为场景中不止一件事发生了变化。实际上有两种不同的情况。您只能使用一个!
纳瓦兹

6

我认为这种“非阻塞”和“异步”的分离是错误的,因为“异步”的主要含义是“非阻塞”。Reactor模式是关于异步(即非阻塞)调用的,但是是关于那些调用的同步(阻塞)处理的。Proactor是关于异步(非阻塞)调用和这些调用的异步(非阻塞)处理的。


1

为了处理TCP连接,有两种竞争的Web体系结构,即基于线程的体系结构和事件驱动的体系结构。

基于线程的架构

实现多线程服务器的最早方法是遵循“每个连接线程”方法。为了控制和限制正在运行的线程数,可以将单个调度程序线程与有限的阻塞队列和线程池一起使用。

调度程序在TCP套接字上为新连接阻塞,并将它们提供给有界阻塞队列。超出队列限制的TCP连接将被丢弃,从而允许接受的连接以理想且可预测的延迟运行。

事件驱动架构

事件驱动的体系结构将线程与连接分开,仅允许将线程用于特定处理程序上的事件。

这个创意概念使“反应堆模式”得以现身并展示出来。基于此体系结构构建的系统由事件创建者和事件使用者组成。

反应堆模式

反应器模式是事件驱动体系结构中用于TCP连接处理的最流行的实现技术。简而言之,它使用单线程事件循环来阻塞事件,并将这些事件分配给相应的处理程序。

只要注册了事件处理程序来处理它们,就不需要其他线程阻塞I / O。考虑到TCP连接,我们可以轻松地将事件引用到以下实例:已连接,已准备好输入,已准备好输出,超时和断开连接。

反应堆模式将模块化应用程序级代码与可重用的反应堆实现解耦。为此,反应堆模式的体系结构由两个重要的参与者组成-Reactor和Handlers。

反应堆

Reactor在单独的线程中运行,并且它通过将工作分配给适当的注册处理程序来对I / O事件(例如已连接,可输入,可输出,超时和断开连接)做出反应。

处理程序

处理程序执行实际的工作或需要通过I / O事件完成的响应。Reactor通过调度适当的处理程序来响应I / O事件。

吉姆·科普林(Jim Coplien)和道格拉斯·施密特(Douglas C. Schmidt)于1995年出版的“程序设计模式语言”是详细解释了反应堆模式的书之一。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.