上一篇介绍了所有的I/O模型,这篇介绍一下现在流行的web server是如何利用I/O模型达到高并发,高性能的服务器的。
从前几篇介绍,我们知道操作系统内核给我们提供了好几种I/O模型,这样我们的应用程序不用阻塞在read/write这些系统调用,而是阻塞在select/poll/epoll.当然这些系统调用帮我们检测大量的fd是否就绪,并提供非阻塞调用模式。
由于AIO模型linux 2.6内核才支持,还没有大量流行起来。 所以包括jdk 1.6 ,以及一些流行的web服务器apache,lighttpd,jetty,都是利用的是epoll模型,来设计高并发服务器。
thread based: 一个客户请求来了,web server从worker线程池分配一个线程去处理。就是说一个sockefd由一个thread去处理。
event based: 一个线程统一去处理所有的连接(socket);等到socket就绪了才分配一个worker线程池里的线程去处理。利用系统调用epoll I/O复用模型,当socket读就绪了才去调度worker线程去处理。这样对比thread based来说,某一时刻,worker线程池有大量idle线程等待着。而对于thread based模型来说,worker线程池可能已经被用完了。
现在流行的高并发,高性能webserver ,采用event based 的有:lighttpd,zeus等。
thread based 缺点: 操作系统能支持的线程数有限; 占用内存高; 线程上下文切换频繁,性能下降; 很脆弱,大量的半tcp攻击就会用完资源,导致无法相应用户请求。
apache 支持三种MPM : Prefork, worker, event;
prefork: 基于thread based 模型。per process per client的模式,一个连接一个子进程来处理的模式。是apache 1.3这个版本开始的。比较老了;基本没人用了吧。
worker: 基于thread based 模型。进程和线程混合模式, 利用per thread per client 的模式,一个连接一个线程去处理,比起prefork模式来说,更加轻量级,支持更多的并发量。
event: 基于event based 模型。worker MPM之上,但是利用event based模型,有一个单独的线程去监听和处理已连接套接字(当然是利用epoll);比起worker来说,支持更多的并发量,而且占用的内存空间跟少。
参考资料:
http://www.kegel.com/c10k.html
http://pl.atyp.us/content/tech/servers.html
http://httpd.apache.org/docs/2.2/mod/event.html