1)传统的线程模型采用阻塞IO模型,每个连接都需要独立的线程完成数据的读取,处理,结果数据返回
当并发量足够大,就会创建大量的线程,耗费资源,而且是阻塞的,如果当前线程没有数据读取,就会一直阻塞,占用资源
2)netty 的线程模型基于IO复用,多个连接共用一个阻塞对象;基于线程池复用线程资源,netty的线程模型叫做Reactor模型,
Reactor模型的主要组成有Reactor线程、handler处理器,Reactor线程在一个单独的线程中运行,负责监听和分发事件,就像一个公司的前台,把来访的客人联系到不同科室的员工,handler负责处理具体的IO事件,它就是实实在在要干活的员工了
根据Reactor的数量和处理资源池线程的数量不同,有3中典型模型:
1)select实现应用程序通过一个阻塞对象监听多路的连接请求
2)select监听到客户端请求事件,进行转发,如果是连接请求,由acceptor通过accept处理连接请求,
然后创建一个handler对象处理后续的业务,如果不是连接事件,reactor会分发调用连接对应的handler来响应
3)handler完成read数据>业务处理》发送结果数据到调用方client
服务器端用一个线程通过IO多路复用搞定所有的IO操作(连接、读、写、断开),编码简单,清晰明了,
但是如果客户端的连接很多,将无法支撑,适合连接的客户端数量较少的场景
1)select实现应用程序通过一个阻塞对象监听多路的连接请求
2)select监听到客户端请求事件,进行转发,如果是连接请求,由acceptor通过accept处理连接请求,
然后创建一个handler对象处理后续的业务,如果不是连接事件,reactor会分发调用连接对应的handler来响应
3)handler只负责响应事件,将read的数据,分发给worker线程池中的某个线程处理,worker分配线程处理
业务,并返回结果给handler
4)handler收到结果,再send给client
可以充分利用多核CPU的处理能力,但是存在多线程间数据共享和访问的问题,reactor负责处理所有事件的监听和响应,
在高并发场景下存在reactor单线程运行的瓶颈问题
让reactor多线程运行
1)reactor主线程mainReactor通过select监听连接事件,收到事件后,通过acceptor处理连接请求
2)当acceptor处理连接事件后,mainReactor将连接分配给subReactor,subReactor将连接加入到连接队列进行监听,
创建handler进行各种事件处理
3)当有新的事件发生时,subReactor就会调用对应的handler进行处理,handler将read的数据,分发给worker线程处理
4)worker线程池分配work线程进行业务处理,并返回结果
5)handler收到响应的结果后,再通过send将结果返回给client
6)reactor主线程可以对应若干个reactor子线程
这种方案应用在nginx主从多进程模型,memcached主从多线程模型,netty主从多线程模型