多线程服务器的适用场合2011-08-07 博客园 陈硕“服务器开发”包罗万象,本文所指的“服务器开发”的含义请见《常用模型》一文,一句话形容是 :跑在多核机器上的 Linux 用户态的没有用户界面的长期运行的网络应用程序。“长期运行”的意思不 是指程序 7x24 不重启,而是程序不会因为无事可做而退出,它会等着下一个请求的到来。例如 wget 不 是长期运行的,httpd 是长期运行的。与前文相同,本文的“进程”指的是 fork() 系统调用的产物。“线程”指的是 pthread_create() 的产物,而且我指的 pthreads 是 NPTL 的,每个线程由 clone() 产生,对应一个内核的 task_struct 。本文所用的开发语言是 C++,运行环境为 Linux。首先,一个由多台机器组成的分布式系统必然是多进程的(字面意义上),因为进程不能跨 OS 边界 。在这个前提下,我们把目光集中到一台机器,一台拥有至少 4 个核的普通服务器。如果要在一台多核 机器上提供一种服务或执行一个任务,可用的模式有:1. 运行一个单线程的进程2. 运行一个多线程的进程3. 运行多个单线程的进程4. 运行多个多线程的进程这些模式之间的比较已经是老生常谈,简单地总结:* 模式 1 是不可伸缩的 (scalable),不能发挥多核机器的计算能力;* 模式 3 是目前公认的主流模式。它有两种子模式:o 3a 简单地把模式 1 中的进程运行多份,如果能用多个 tcp port 对外提供服务的话;o 3b 主进程+woker进程,如果必须绑定到一个 tcp port,比如 httpd+fastcgi。* 模式 2 是很多人鄙视的,认为多线程程序难写,而且不比模式 3 有什么优势;* 模式 4 更是千夫所指,它不但没有结合 2 和 3 的优点,反而汇聚了二者的缺点。本文主要想讨论的是模式 2 和模式 3b 的优劣,即:什么时候一个服务器程序应该是多线程的。从功能上讲,没有什么是多线程能做到而单线程做不到的,反之亦然,都是状态机嘛(我很高兴看到 反例)。从性能上讲,无论是 IO bound 还是 CPU bound 的服务,多线程都没有什么优势。那么究竟为 什么要用多线程?在回答这个问题之前,我先谈谈必须用必须用单线程的场合。必须用单线程的场合