Netty(2)
Reactor模式
- 通过一个或多个输入同时传递给服务处理器的模式(基于事件驱动)。
- 服务器端程序处理传入的多个请求,并将它们同步分派到相应处理线程。
- 使用IO复用监听事件,收到事件后,分发给某个线程(进程)。
举例子:
有家独特的医院,当患者来了要门诊(请求Event),入口处前台服务员(ServiceHandler)先迎客,该服务员接着送这个顾客到空闲屋子处理业务进行门诊治疗(EventHandler)。
单Reactor单线程
- Select是前面IO复用模型介绍的标准网络编程API,可以实现应用程序通过一个阻塞对象监听多路连接请求。
- Reactor 对象通过Select监听客户端请求事件,收到事件后Dispatch进行分发处理连接完成后的后续业务处理。
- 如果是建立连接请求事件,则由Acceptor通过Accept处理连接请求,然后创建一个Handler对象处理连接完成后的后续业务处理
- 如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来响应。
- Handler会完成Read->业务处理->Send 的完整业务流程。
举例子:
有家独特的医院,当患者来前台导诊员(Reactor主线程)询问业务(select判断),患者挂号(请求Event,建立连接Acceptor),人再来了后要求治疗(dispatch 准备门诊治疗)该导诊员送该顾客到空闲屋子处理业务进行门诊治疗(EventHandler)。
单Reactor多线程
- Reactor对象通过select监控后客户端请求事件,收到事件后,通过dispatch进行分发
- 如果建立连接请求,则右Acceptor通过accept处理连接请求,然后创建一个Handler对象处理完成连接后的各种事件
- 如果不是连接请求,则有reactor分发调用连接对应的Handler来处理
- Handler只负责响应事件,不做具体业务处理,通过read读取数据后,会分发给后面的worker线程池的某个线程处理业务。
- worker线程池会分配独立线程,完成真正的业务,并将结果返回给Handler。
- Handler收到响应后通过send将结果返回给client。
举例子:
有家独特的医院,当患者来了,前台导诊员(Reactor主线程)询问业务(select判断),患者要挂号(连接请求Event)。人再来了要求治疗(处理请求Event)后该导诊员送该顾客到空闲屋子由医生们(Worker线程池)出一人门诊治疗(EventHandler),导诊员将结果反馈给患者(返回Client)。
主从Reactor多线程
- Reactor主线程MainReactor对象通过select监听连接事件,收到事件后,通过Acceptor处理连接事件。
- 当Acceptor处理连接事件后,MainReactor将连接分配给SubReactor。
- SubReactor将连接加入到连接队列进行监听,并创建Handler进行事件处理。
- 当有新事件发生时,SubReactor就会调用对应Handler处理。
- Handler通过Read读取数据,分发给后面的Worker线程处理。
- Worker线程池分配独立的Worker 线程进行业务处理,并返回结果。
- Handler收到响应结果后,再通过send返回给Client。
- Reactor主线程可以对应多个Reactor子线程。
举例子:
有家独特的医院,当患者来了,前台导诊员(Reactor主线程)询问业务(select判断)。患者要挂号(连接请求Event,Acceptor登记到医院系统),人再来了要求治疗(处理请求Event)前台导诊员转给一个分诊服务员(Reactor子线程,有多个)送该顾客到空闲房间由医生们(Worker线程池)出一人处理业务门诊治疗(EventHandler)由引路服务员(Reactor 子线程的Handler的send方法)通知结果给患者(返回Client)。
Netty模型
-
Netty抽象出两组线程池BossGroup 专门负责接收客户端连接,WorkerGroup专门负责网络的读写。
-
BossGroup和WorkerGroup对应都是NioEventLoopGroup。
-
NioEventLoopGroup相当于一个事件循环组,这个组中含有多个事件循环,每一个事件循环时NioEventLoop
-
NioEventLoop表示一个不断循环的执行处理任务的线程,每个NioEventLoop都有一个Selector,用于监听绑定再其上的网络通讯。
-
NioEventLoopGroup可以有多个线程,即可以含有多个NioEventLoop
-
每个Boss NioEventLoop 执行有三步
6.1 轮询accept事件
6.2 处理accept事件,与client建立连接,生成NioSocketChannel,并将其注册到某个woker NioEventLoop上的selector。
6.3 处理任务队列的任务,即 runAllTasks。
-
每个Worker NioEventLoop循环执行的步骤:
7.1 轮询read,wirte事件。
7.2 处理i/o事件,即read,write事件,在对应NioSocketChannel处理。
7.3 处理任务队列的任务,即runAllTasks。
-
每个Worker NioEventLoop处理业务时,会使用Pipeline管道,Pipeline中包含了Channel,即通过Pipeline可以获取到对应管道,管道中维护了很多的处理器。
举例子:
有家独特的医院,当患者来了,前台(Boss Group)其中队列里(TaskQueue)一直等待接待患者的前台服务员(NioEventLoop)向患者询问业务(select判断)。患者要挂号(accept事件)前台直接处理。已挂号的人再来了就直接到分诊台(WorkerGroup)要求治疗(处理请求事件),分诊台中一直等待接待患者的分诊台服务员们(多个NioEventLoop),空闲的一个分诊台服务员出来送该患者到空闲房间由医生们出来一人(PipelineHandler)进行门诊治疗。
当人流量很大时,第一种模型患者可安置处理的数量太少;第二种模型受限于只有一个前台服务员,人流全部拥塞到前台;第三种模型挂号和治疗的人分流,治疗的人有多个分诊服务员引导;第四种模型多个前台服务员,多个分诊服务员,可以更好的处理。这个情况即模拟高并发场景,四种模型处理高并发的性能依次增强。