单服务器高性能模式: PPC&TPC ########################### * PPC: Process Per Connection * TPC: Thread Per Connection 高性能又是最复杂的一环,磁盘、操作系统、CPU、内存、缓存、网络、编程语言、架构等,每个都有可能影响系统达到高性能:: 一行不恰当的 debug 日志,就可能将服务器的性能从 TPS 30000 降低到 8000; 一个 tcp_nodelay 参数,就可能将响应时间从 2 毫秒延长到 40 毫秒 高性能架构设计主要集中在两方面:: 尽量提升单服务器的性能,将单服务器的性能发挥到极致。 如果单服务器无法支撑性能,设计服务器集群方案。 .. note:: 除了以上两点,最终系统能否实现高性能,还和具体的实现及编码相关。但架构设计是高性能的基础,如果架构设计没有做到高性能,则后面的具体实现和编码能提升的空间是有限的。形象地说,架构设计决定了系统性能的上限,实现细节决定了系统性能的下限。 单服务器高性能的关键之一就是服务器采取的并发模型,并发模型有如下两个关键设计点:: 1. 服务器如何管理连接 2. 服务器如何处理请求 以上两个设计点最终都和操作系统的 I/O 模型及进程模型相关:: 1. I/O 模型:阻塞、非阻塞、同步、异步 2. 进程模型:单进程、多进程、多线程 PPC === .. note:: 每次有新的连接就新建一个进程去专门处理这个连接的请求,这是传统的 UNIX 网络服务器所采用的模型。 PPC 模式实现简单,比较适合服务器的连接数没那么多的情况,例如数据库服务器。 当服务器的并发和访问量从几十剧增到成千上万,这种模式的弊端就凸显出来:: 1. fork 代价高 2. 父子进程通信复杂 3. 支持的并发连接数量有限 prefork ------- prefork 就是提前创建进程(pre-fork)。系统在启动的时候就预先创建好进程,然后才开始接受用户的请求,当有新的连接进来的时候,就可以省去 fork 进程的操作,让用户访问更快、体验更好 TPC === .. note:: 每次有新的连接就新建一个线程去专门处理这个连接的请求 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 网络编程》三卷本