线程模型
-
传统线程模型
采用阻塞IO模型,一个链接一个线程问题:
- 当并发过多,创建大量线程会造成资源的大量占用
- 连接建立后,很可能一直阻塞在等待读和写的状态
-
Reactor模型(反应堆模型)/Dispatcher模型(分发模式)
Reactor 模式,是指通过一个或多个输入同时传递给服务处理器的服务请求的事件驱动处理模式。针对第一个问题,我们使用线程池,不是每个连接一个线程,而是在线程建立以后,把业务处理的任务交给线程去处理,这样一个线程就可以处理多个链接的业务了
针对第二个问题,我们使用IO复用模型,多个连接公用一个阻塞对象,IO复用模型,当某个连接有数据可以处理,操作系统会通知应用程序
-
单Reactor单线程
就是一个接待员,一个服务员
优点:简单,没有多线程,没有进程通信
缺点:性能,无法发挥多核的极致,一个handler卡死,导致当前进程无法使用,IO和CPU不匹配
场景:客户端有限,业务处理快,比如redis
-
单Reactor多线程
就是一个接待员,多个服务员,但是真正的多线程是在Worker中,你可以认为是多个厨师
优点:充分利用的CPU
缺点:进程通信,复杂,Reactor承放了太多业务,高并发下可能成为性能瓶颈
-
主从Reactor多线程
就是多个接待员,多个服务员,多个厨师
主Reactor负责建立连接,建立连接后的句柄丢给子Reactor,子Reactor负责监听所有事件进行处理
优点:职责明确,分摊压力
Nginx/netty/memcached都是使用的这
-
-
Proactor 模型(前摄器)
reactor中等待时间发生,然后让实现准备好的handler去处理,后者来实际读写,它是同步非阻塞的线程模型
如果IO改为异步,交给操作系统来完成,则可以进一步提高效率,这就是异步网络模型,Proactor
Proactor读写在内核中完成,Reactor读写在Handler里面完成
1)编程复杂性,由于异步操作流程的事件的初始化和事件完成在时间和空间上都是相互分离的,因此开发异步应用程序更加复杂。应用程序还可能因为反向的流控而变得更加难以 Debug;
2)内存使用,缓冲区在读或写操作的时间段内必须保持住,可能造成持续的不确定性,并且每个并发操作都要求有独立的缓存,相比 Reactor 模式,在 Socket 已经准备好读或写前,是不要求开辟缓存的;
3)操作系统支持,Windows 下通过 IOCP 实现了真正的异步 I/O,而在 Linux 系统下,Linux 2.6 才引入,目前异步 I/O 还不完善。