3.2 单线程服务器的常用模型

Reactor 模型

non-blocking IO + IO multiplexing。
image.png
这种基于事件驱动的编程模型也有其本质缺点要求事件回调函数必须是非阻塞的。对于涉及网络IO的请求响应式协议,它容易割裂业务逻辑,使其散布于多个回调函数中,不利于维护和理解。

3.3 多线程服务器的常用模型

默认情况下,使用 non-blocking IO + one loop per thread模式。

3.3.1 one loop per thread

在这种模式中,每个 IO 线程都有一个 event loop(Reactor),用于处理读写和定时事件。优点如下:

  • 线程数量基本固定,不会频繁创建与销毁
  • 可以轻松在线程间调配负载
  • IO 事件发生的线程是固定的,同一个 TCP 连接不必考虑事件并发。

EventLoop 代表了线程的主循环,需要让哪个线程工作就把 timer 或 TCP 连接注册到哪个线程的 loop 中即可。对实时性有要求的 connection 可以单独用一个线程数据量大的 connection 可以独占一个线程,并把数据处理任务分摊到另外几个计算线程中(线程池)。

3.4 进程间通信只用 TCP

TCP 端口由一个进程独占,且 OS 会自动回收。
image.png

分布式系统中使用 TCP 长连接
一个分布式系统由运行在多台机器上的多个进程组成进程之间采用 TCP 长连接。优点如下:

  • 容易定位分布式系统中的服务之间的依赖关系。在机器上运行netstat -tpna|grep :port就能列出用到某服务的客户端地址,然后在客户机器上用netstatlsof找出是哪个进程发起的连接。于是在迁移服务时能防止出现 outage。TCP 短连接和 UDP 不具备这一特性。
  • 通过接收/发送队列的长度也容易定位网络或程序故障。 正常运行时,netstat打印的 Recv-Q 和Send-Q 都应该接近 0,或者在 0 附近摆动。 如果 Recv-Q 保持不变或持续增加,则通常意味着服务进程的处理速度变慢,可能发生了死锁或阻塞。如果 Send-Q 保持不变或持续增加,有可能是对方服务器太忙、来不及处理,也有可能是网络中间某个路由器或交换机故障造成丢包,甚至对方服务器掉线,这些因素都可能表现为数据发送不出去。通过持续监控 Recv-Q 和 Send-Q 就能及早预警性能或可用性故障:

image.png

3.5 多线程服务器的适用场合

处理并发连接成为开发服务端程序的基本任务呀,主要有两种方式:
image.png

多核机器的运作模式有:

  • 运行一个单线程的进程(不可伸缩,不能发挥多核机器的能力)
  • 运行一个多线程的进程(相比③没有优势)
  • 运行多个单线程的进程
    • a. 简单把①中的进程运行多份
    • b. 主进程+worker 进程,如果必须绑定一个 TCP port,比如 httpd+fastcgi
  • 运行多个多线程的进程(傻逼)

    3.5.1 必须使用单线程的场合

    有两种场合必须使用单线程:

  • 程序可能会fork()只有单线程程序可以**fork()**

  • 限制程序的 CPU 占用率。单线程最多占满一个核,不会影响客户主要服务。

3.5.2 单线程程序的优缺点

Event loop 有一个明显缺点:是非抢占式的
image.png

多线程不一定有想象中的性能优势——如果用很少的 CPU 负载就能让 IO 跑满,或者用很少的 IO 流量就能让 CPU 跑满,那么多线程其实并无提升。
例如: 对于静态Web服务器,或者FTP服务器CPU 的负载较轻主要瓶颈在磁盘 IO 和网络 IO 方面。这时候往往一个单线程的程序(模式1)就 能撑满 IO。用多线程并不能提高吞吐量,因为 IO 硬件容量已经饱和了。 同理,这时增加 CPU 数目也不能提高吞吐量

3.5.3 适用多线程的场景

场景:提高响应速度,让 IO 和计算互相重叠,降低 latency(从接收/等待到完成的全程时间)。

线程的分类

  1. IO 线程主循环是 IO 多路复用,阻塞地等在 select/poll/epoll_wait 系统调用上。也处理定时事件。功能也不止 IO,简单的计算也可以放入(编解码)。
  2. 计算线程:主循环是 blockingqueue,阻塞等待在条件变量上。这类线程一般位于 thread pool 中。通常不涉及 IO,一般要避免任何阻塞操作。
  3. 第三方库所用的线程,比如 logging / database connection。

服务器程序一般不会频繁启动和终止线程几乎只在程序启动的时候创建,在服务运行期间是不创建线程的

第三章末的问答很有价值,多看多钻研。