网络模块的性能瓶颈分析
对于单个请求来说,请求流程是:客户端(生产者 / 消费者)构建请求后,向服务端发送请求包 -> 服务端接收包后,将包交给业务线程处理 -> 业务线程处理完成后,将结果返回给客户端。其中可能消耗性能的有三个点。
- 编解码的速度。
- 网络延迟。也就是客户端到服务端的网络延迟,这一点在软件层面几乎无法优化,取决于网络链路的性能,跟网络模块无关。
- 服务端 / 客户端网络模块的处理速度。发送 / 接收请求包后,包是否能及时被处理,比如当逻辑线程处理完成后,网络模块是否及时回包。
对于并发请求来说,在单个请求维度的问题的基础上,还需要处理高并发、高 QPS、高流量等场景带来的性能问题。主要包含三个方面。
- 高效的连接管理:当客户端和服务端之间的 TCP 连接数很多,如何高效处理、管理连接。
- 快速处理高并发请求:当客户端和服务端之间的 QPS 很高,如何快速处理(接收、返回)请求。
- 大流量场景:当客户端和服务端之间的流量很高,如何快速吞吐(读、写)数据。
高性能网络模块的设计实现
基于多路复用技术管理 TCP 连接
IO 多路复用技术,是指通过把多个 IO 的阻塞复用到同一个 selector 的阻塞上,让系统在单线程的情况下可以同时处理多个客户端请求。最大的优势是系统开销小,系统不需要创建额外的进程或者线程,降低了维护的工作量,也节省了资源。
基于 Reactor 模型处理高并发请求
Reactor 模型是一种处理并发服务请求的事件设计模式,当主流程收到请求后,通过多路分离处理的方式,把请求分发给相应的请求处理器处理。如下图所示,Reactor 模式包含 Reactor、Acceptor、Handler 三个角色。
- Reactor:负责监听和分配事件。收到事件后分派给对应的 Handler 处理,事件包括连接建立就绪、读就绪、写就绪等。
- Acceptor:负责处理客户端新连接。Reactor 接收到客户端的连接事件后,会转发给 Acceptor,Acceptor 接收客户端的连接,然后创建对应的 Handler,并向 Reactor 注册此 Handler。
- Handler:请求处理器,负责业务逻辑的处理,即业务处理线程。
单 Reactor 单进程模型,不适用于计算密集型的场景,只适用于业务处理非常快速的场景。
单 Reactor 多线程模型,优点是 Handler 收到响应后通过 send 把响应结果返回给客户端,降低 Reactor 的性能开销,提升整个应用的吞吐。缺点是 Handler 使用多线程模式,带来了多线程竞争资源的开销,同时涉及共享数据的互斥和保护机制,实现比较复杂。另外,单个 Reactor 承担所有事件的监听、分发和响应,对于高并发场景,容易造成性能瓶颈。
主从 Reactor 多线程模型,是让 Reactor 也变为了多线程。主线程只负责接收新连接,子线程负责完成后续的业务处理。
当前业界消息队列的网络模型,比如 Pulsar、Kafka、RocketMQ,为了保证性能,都是基于主从 Reactor 多线程模型开发的。
此文章为11月Day4学习笔记,内容来源于极客时间《深入拆解消息队列 47 讲》