主页

索引

模块索引

搜索页面

单服务器高性能模式: PPC&TPC

  • PPC: Process Per Connection

  • TPC: Thread Per Connection

高性能又是最复杂的一环,磁盘、操作系统、CPU、内存、缓存、网络、编程语言、架构等,每个都有可能影响系统达到高性能:

一行不恰当的 debug 日志,就可能将服务器的性能从 TPS 30000 降低到 8000;
一个 tcp_nodelay 参数,就可能将响应时间从 2 毫秒延长到 40 毫秒

高性能架构设计主要集中在两方面:

尽量提升单服务器的性能,将单服务器的性能发挥到极致。
如果单服务器无法支撑性能,设计服务器集群方案。

备注

除了以上两点,最终系统能否实现高性能,还和具体的实现及编码相关。但架构设计是高性能的基础,如果架构设计没有做到高性能,则后面的具体实现和编码能提升的空间是有限的。形象地说,架构设计决定了系统性能的上限,实现细节决定了系统性能的下限。

单服务器高性能的关键之一就是服务器采取的并发模型,并发模型有如下两个关键设计点:

1. 服务器如何管理连接
2. 服务器如何处理请求

以上两个设计点最终都和操作系统的 I/O 模型及进程模型相关:

1. I/O 模型:阻塞、非阻塞、同步、异步
2. 进程模型:单进程、多进程、多线程

PPC

备注

每次有新的连接就新建一个进程去专门处理这个连接的请求,这是传统的 UNIX 网络服务器所采用的模型。

PPC 模式实现简单,比较适合服务器的连接数没那么多的情况,例如数据库服务器。

当服务器的并发和访问量从几十剧增到成千上万,这种模式的弊端就凸显出来:

1. fork 代价高
2. 父子进程通信复杂
3. 支持的并发连接数量有限

prefork

prefork 就是提前创建进程(pre-fork)。系统在启动的时候就预先创建好进程,然后才开始接受用户的请求,当有新的连接进来的时候,就可以省去 fork 进程的操作,让用户访问更快、体验更好

TPC

备注

每次有新的连接就新建一个线程去专门处理这个连接的请求

prethread

和 prefork 类似,prethread 模式会预先创建线程,然后才开始接受用户的请求,当有新的连接进来的时候,就可以省去创建线程的操作,让用户感觉更快、体验更好。

prethread 理论上可以比 prefork 支持更多的并发连接,Apache 服务器 MPM worker 模式默认支持 16 × 25 = 400 个并发处理线程。

思考

高并发需要根据两个条件划分:

连接数量,请求数量
1. 海量连接(成千上万)海量请求:例如抢购,双十一等
    面对海量的连接,使用集群,并且单机使用 『IO 复用模型』或者『异步 IO 模型』
    针对海量的请求,使用集群,并且单机使用『多进程处理』或『多线程』
2. 常量连接(几十上百)海量请求:例如中间件,比如数据库,redis,kafka
    适合 TPC 和 PPC,可使用阻塞 IO
    当然使用非阻塞 IO 也没问题,如:
      Activemq 既支持 BIO 也支持 NIO
      Rocketmq 也是使用 netty 这样的 NIO 框架
3. 海量连接常量请求:例如门户网站
4. 常量连接常量请求:例如内部运营系统,管理系统

PPC 和 TPC适合场景:

PPC 和 TPC 能够支持的最大连接数差不多,都是几百个
这两种方式明显不支持高连接数的场景

所以 PPC 和 TPC 适合:
1. 常量连接海量请求。比如数据库,redis,kafka 等等
2. 常量连接常量请求。比如企业内部网址

tpc 异常时整个服务器就挂了,而 ppc 不会,所以 ppc 适合数据库,中间件这类

ppc 的服务器,连接满了后新的连接进不来,但旧的连接发送请求是没问题的

ppc 和 tpc 模式一般如何根据硬件配置计算可支持的并发数呢
一般按照 CPU 核数 * 2 来计算

不是说用了多进程就是 PPC,而是说用进程来处理连接才是 PPC
所以 redis 用 fork 来创建持久化进程不是 PPC。

BIO:

一个线程处理一个请求。
缺点:
    并发量高时,线程数较多,浪费资源。
    如果编程控制不善,可能造成系统资源耗尽。
Tomcat7 或以下,在 Linux 系统中默认使用这种方式。
可以适用于小到中规模的客户端并发数场景,无法胜任大规模并发业务。

NIO:

利用多路复用 IO 技术,可以通过少量的线程处理大量的请求。
Tomcat8 在 Linux 系统中默认使用这种方式。
Tomcat7 必须修改 Connector 配置来启动。

NIO 最适用于 “高并发” 的业务场景,
所谓高并发是指 1ms 内至少同时有成百上千个连接请求准备就绪,其他情况下 NIO 技术发挥不出它明显的优势

BIO&NIO&AIO:

BIO:阻塞 io,PPC 和 TPC 属于这种
NIO:多路复用 io,reactor 就是基于这种技术
AIO:异步 io,Proactor 就是基于这种技术

一些常见的细节点如下:

java:推荐看 disruptor 的设计论文,包括 false sharing, 并发无锁,ring buffer 等;
网络:tcp_nodelay,NIO;
内存:内存池,对象池,数据结构
存储:磁盘尾部追加,LSM;

异步 io 性能相比 io 复用没有明显优势,但操作系统设计比较复杂:

Linux 上主流的是 epoll io 复用
Windows 上是 IOCP 的异步 io

参考

  • 更多内容你可以参考《UNIX 网络编程》三卷本

主页

索引

模块索引

搜索页面