程序员肖邦的博客 享受编程和技术所带来的快乐

单服务器的高性能设计模式

2019-01-29
肖邦

高性能是我们每一个程序员的追求,磁盘、操作系统、CPU、内存、缓存、网络、编程语言、架构等都可能会影响到系统的高性能,因此高性能是一件很复杂、具有挑战性的事情。

关于高性能架构设计

站在架构师的角度,高性能架构设计主要集中在两方面:

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

最终系统能否实现高性能,还和具体的实现与编码相关。架构设计是高性能的基础,可以这么说,架构设计决定了系统性能的上限,实现细节决定了系统性能的下限。而单服务器高性能的关键之一就是服务器采用的并发模型,并发模型有如下两个关键设计点:

  • 服务器如何管理连接
  • 服务器如何处理请求

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

  • IO 模型:阻塞、非阻塞、同步、异步
  • 进程模型:单进程、多进程、多线程

PPC

PPC 是 Process Per Connection 的缩写,含义是指每次有新的连接就新建一个进程去专门处理这个连接的请求,这是传统的 UNIX 网络服务器采用的模型,基本流程图是: PPC

  • 父进程接受连接
  • 父进程 fork 子进程
  • 子进程处理连接的读写请求
  • 子进程关闭连接

PPC 模式实现简单,比较适合服务器连接数较少的情况,如数据库服务器。世界上第一个 web 服务器就采用了这种模式,互联网兴起之后,这种模式弊端主要体现在这几个方面:

  • fork 代价高:需要分配很多内核资源,需要将内存映像从父进程复制到子进程。
  • 父子进程通信复杂:需要采用 IPC 之类的进程间通信方案。
  • 支持的并发连接数量有限:PPC 方案能处理的并发连接数量最大也就几百。

prefork

PPC 模式中,当连接进来时才 fork 新进程来处理连接请求,由于 fork 进程代价高,用户访问时可能感觉比较慢,prefork 模式的出现就是为了解决这个问题。prefork 就是系统在启动时预先创建好进程,当有新的连接进来时,就可以省去 fork 进程的操作,让用户访问更快、体验更好。

prefork

prefork 实现关键就是多个子进程都 accept 同一个 socket,当有新连接进入时,操作系统保证只有一个进程能最后 accept 成功。不过这里也存在一个 惊群 现象,就是虽然只有一个子进程能 accept 成功,但所有阻塞在 accept 上的子进程都会被唤醒,导致了不必要的进程调度和上下文切换,不过 Linux 2.6 后内核已经解决了 accept 惊群的问题。prefork 仍然存在父子进程通信复杂、支持的并发连接数量有限的问题,目前实际应用不多。


Comments

Content