WebFlux基于Reactor线程模型,WebFlux又是AIO的实现.同时Netty也是使用的Reactor线程模型.所以有必要了解下Reactor线程模型,以应对多种不同技术的变更cuiyaonan2000@163.com
根据大神Doug Lea 在 《Scalable IO in Java 》中的介绍,Reacotr模型主要分为三个角色(如下的角色都是线程,只是他们的作用域不一样cuiyaonan2000@163.com)
- Reactor:把IO事件分配给对应的handler处理(这里其实是个控制线程,根据任务的类型,转发到Acceptor或者Handler让他们来处理)
- Acceptor:处理客户端连接事件
- Handler:处理具体的业务
根据Reactor的数量和处理资源的线程数量的不同,分为三类:
- 单Reactor单线程模型
- 单Reactor多线程模型
- 多Reactor多线程模型
这种模型在Reactor中处理事件,并分发事件,如果是连接事件交给acceptor处理,如果是读写事件和业务处理就交给handler处理,但始终只有一个线程执行所有的事情
该线程模型的不足:
- 仅用一个线程处理请求,对于多核资源机器来说是有点浪费的(Reactor线程是单线程)
- 当处理读写任务的线程负载过高后,处理速度下降,事件会堆积,严重的会超时,可能导致客户端重新发送请求,性能越来越差(这个单线程是指业务处理的Handler是单线程的)
- 单线程也会有可靠性的问题
这种模型和第一种模型到的主要区别是把业务处理从之前的单一线程脱离出来,换成线程池处理,也就是Reactor线程只处理连接事件和读写事件,业务处理交给线程池处理,充分利用多核机器的资源、提高性能并且增加可靠性(即业务处理的单线程换成线程池)
该线程模型的不足:
- Reactor线程承担所有的事件,例如监听和响应,高并发场景下单线程存在性能问题
这种模型下和第二种模型相比是把Reactor线程拆分了mainReactor和subReactor两个部分,mainReactor只处理连接事件,读写事件交给subReactor来处理。业务逻辑还是由线程池来处理
mainRactor只处理连接事件,用一个线程来处理就好。处理读写事件的subReactor个数一般和CPU数量相等,一个subReactor对应一个线程,业务逻辑由线程池处理 这种模型使各个模块职责单一,降低耦合度,性能和稳定性都有提高这种模型在许多项目中广泛应用,比如Netty的主从线程模型等
餐厅一般有接待员和服务员,接待员负责在门口接待顾客,服务员负责全程服务顾客 Reactor的三种线程模型可以用接待员和服务员类比
- 单Reactor单线程模型:接待员和服务员是同一个人,一直为顾客服务。客流量较少适合
- 单Reactor多线程模型:一个接待员,多个服务员。客流量大,一个人忙不过来,由专门的接待员在门口接待顾客,然后安排好桌子后,由一个服务员一直服务,一般每个服务员负责一片中的几张桌子
- 多Reactor多线程模型:多个接待员,多个服务员。这种就是客流量太大了,一个接待员忙不过来了