从最先看的《Head First 设计模式》到后面看的一些书,里面对于设计模式的讲解大部分都是从抽象概念介绍一个设计模式是什么和一些例子。这些例子大多都是买咖啡(head first真的喜欢以咖啡举例),玩具鸭子之类的。我也看过相似《Javascript设计模式与开发实践》,里面举例的时候会以一些做者实际开发中碰到的例子。这个系列是我平常学习中遇到设计模式的一个总结,但愿能帮助到你们。前端
文章应该会在个人学习过程当中不断更新。react
今天在研究《Node.js design patterns 2nd》的时候提到了反应器模式,我总结下本身所学和研究并写篇博客总结一下。linux
反应器设计模式(Reactor pattern)是一种为处理服务请求并发 提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,而后同步地派发这些请求至相关的请求处理程序。web
The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers. --GoF设计模式
反正咱们不玩定义。咱们先以一个餐饮店为例,假设每个人来就餐就是一个I/O操做,他会先看一下菜单,而后点餐。就像一个网站会有不少的请求,要求服务器作一些事情。处理这些就餐事件的就是咱们须要解决的问题了。服务器
在多线程处理的方式会是这样的:网络
一我的来就餐,一个服务员去服务,而后客人点菜。 服务员将菜单给后厨。多线程
十我的来就餐,十个服务员去服务……并发
这个就是多线程的处理方式,一个请求到来,就会有一个线程服务。很显然这种方式在人少的状况下会有很好的用户体验,每一个客人都感受本身是VIP,专人服务的。若是餐厅一直这样同一时间最多来10个客人,这家餐厅是能够很好的服务下去的。异步
那么问题来了,若是这家餐厅生意很是好,同时就餐人数(网站并发访问量)达到100人呢,给每一个分配个服务员那餐馆怕不是要破产。
尽管能够考虑使用相似线程池的方法,组成一个10个服务员的线程池,一个服务员服务完一我的后继续去服务下一个。 可是这样有一个比较严重的缺点就是,若是某个客人点菜很慢(读写文件,网路请求等操做和内存读写比起来很是的慢),其余人可能就要等好长时间了。
其实当客人在点菜的时候,大部服务员服务的时候都在等着客人的菜上好后才去服务下一个(阻塞),其实干的活不是太多。若是客人须要点餐的时候直接告诉服务员,我须要宫保鸡丁,作好以后直接放到14桌,而后服务员就能够去服务下一我的了,这样是否是可以有效利用服务员的资源?
其实这就是基于事件的解决方案,“作好以后放到14桌”其实就是回调函数。
先直接贴一下Douglas C. Schmidt 大佬的论文 An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events.pdf
Node.js 这几年很是火,借助 js 天生的事件驱动机制和 V8高性能引擎,让编写高并发的web应用门槛下降了许多,固然这背后还要得益于基于事件驱动的 Reactor 模式,让自己只支持单线程执行的 js 可以胜任现在高并发环境下的服务端应用。
下面这张图就是一个应用里面使用Reactor模式的图示
前端的同窗对于Event Loop应该比较熟吧。
如今再来从新看一下定义是否是清晰了一点?
反应器设计模式(Reactor pattern)是一种为处理服务请求并发 提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,而后同步地派发这些请求至相关的请求处理程序。
其实Event Demultiplexer以前我就有过一些了解不过没有深刻,当时是在作计算机网络大做业的时候,当时选题是作一个Web Server,相似Apache、Nginx那种。当时研究高并发模型的时候接触到了I/O多路复用(multiplexing),其实就是事件驱动,当时用的libevent的库,好像是基于的linux的epoll系统调用实现的。