Nginx 才短短几年, 就拿下了 web 服务器大笔江山, 众所周知, Nginx 在处理大并发静态请求方面, 效率明显高于 httpd, 甚至能轻松解决 C10K 问题.
在高并发连接的情况下, Nginx 是 Apache 服务器不错的替代品. Nginx 同时也可以作为 7 层负载均衡服务器来使用. 根据我的测试结果, Nginx 0.7.14 + PHP 5.2.6 (FastCGI) 可以承受 3 万以上的并发连接数, 相当于同等环境下 Apache 的 10 倍.
一般来说, 4GB 内存的服务器 + Apache(prefork 模式)一般只能处理 3000 个并发连接, 因为它们将占用 3GB 以上的内存, 还得为系统预留 1GB 的内存. 我曾经就有两台 Apache 服务器, 因为在配置文件中设置的 MaxClients 为 4000, 当 Apache 并发连接数达到 3800 时, 导致服务器内存和 Swap 空间用满而崩溃.
而这台 Nginx 0.7.14 + PHP 5.2.6 (FastCGI) 服务器在 3 万并发连接下, 开启的 10 个 Nginx 进程消耗 150M 内存(15M*10=150M), 开启的 64 个 php-cgi 进程消耗 1280M 内存(20M*64=1280M), 加上系统自身消耗的内存, 总共消耗不到 2GB 内存. 如果服务器内存较小, 完全可以只开启 25 个 php-cgi 进程, 这样 php-cgi 消耗的总内存数才 500M.
在 3 万并发连接下, 访问 Nginx 0.7.14 + PHP 5.2.6 (FastCGI) 服务器的 PHP 程序, 仍然速度飞快.
为什么 Nginx 在处理高并发方面要优于 httpd, 我们先从两种 web 服务器的工作原理以及工作模式说起.
apache 三种工作模式
我们都知道 Apache 有三种工作模块, 分别为 prefork,worker,event.
prefork: 多进程, 每个请求用一个进程响应, 这个过程会用到 select 机制来通知.
worker: 多线程, 一个进程可以生成多个线程, 每个线程响应一个请求, 但通知机制还是 select 不过可以接受更多的请求.
event: 基于异步 I/O 模型, 一个进程或线程, 每个进程或线程响应多个用户请求, 它是基于事件驱动 (也就是 epoll 机制) 实现的.
4.2 prefork 的工作原理
如果不用 "--with-mpm" 显式指定某种 MPM,prefork 就是 Unix 平台上缺省的 MPM. 它所采用的预派生子进程方式也是 Apache1.3 中采用的模式. prefork 本身并没有使用到线程, 2.0 版使用它是为了与 1.3 版保持兼容性; 另一方面, prefork 用单独的子进程来处理不同的请求, 进程之间是彼此独立的, 这也使其成为最稳定的 MPM 之一.
4.3 worker 的工作原理
相对于 prefork,worker 是 2.0 版中全新的支持多线程和多进程混合模型的 MPM. 由于使用线程来处理, 所以可以处理相对海量的请求, 而系统资源的开销要小于基于进程的服务器. 但是, worker 也使用了多进程, 每个进程又生成多个线程, 以获得基于进程服务器的稳定性, 这种 MPM 的工作方 式将是 Apache2.0 的发展趋势.
4.4 event 基于事件机制的特性
一个进程响应多个用户请求, 利用 callback 机制, 让套接字复用, 请求过来后进程并不处理请求, 而是直接交由其他机制来处理, 通过 epoll 机制来通知请求是否完成; 在这个过程中, 进程本身一直处于空闲状态, 可以一直接收用户请求. 可以实现一个进程程响应多个用户请求. 支持持海量并发连接数, 消耗更少的资源.
如何提高 Web 服务器的并发连接处理能力
有几个基本条件:
1. 基于线程, 即一个进程生成多个线程, 每个线程响应用户的每个请求.
2. 基于事件的模型, 一个进程处理多个请求, 并且通过 epoll 机制来通知用户请求完成.
3. 基于磁盘的 AIO(异步 I/O)
4. 支持 mmap 内存映射, mmap 传统的 web 服务器, 进行页面输入时, 都是将磁盘的页面先输入到内核缓存中, 再由内核缓存中复制一份到 web 服务器上, mmap 机制就是让内核缓存与磁盘进行映射, web 服务器, 直接复制页面内容即可. 不需要先把磁盘的上的页面先输入到内核缓存去.
刚好, Nginx 支持以上所有特性. 所以 Nginx 官网上说, Nginx 支持 50000 并发, 是有依据的.
Nginx 优异之处
传统上基于进程或线程模型架构的 web 服务通过每进程或每线程处理并发连接请求, 这势必会在网络和 I/O 操作时产生阻塞, 其另一个必然结果则是对内存或 CPU 的利用率低下. 生成一个新的进程 / 线程需要事先备好其运行时环境, 这包括为其分配堆内存和栈内存, 以及为其创建新的执行上下文等. 这些操作都需要占用 CPU, 而且过多的进程 / 线程还会带来线程抖动或频繁的上下文切换, 系统性能也会由此进一步下降. 另一种高性能 web 服务器 / web 服务器反向代理: Nginx(Engine X),nginx 的主要着眼点就是其高性能以及对物理计算资源的高密度利用, 因此其采用了不同的架构模型. 受启发于多种操作系统设计中基于 "事件" 的高级处理机制, nginx 采用了模块化, 事件驱动, 异步, 单线程及非阻塞的架构, 并大量采用了多路复用及事件通知机制. 在 nginx 中, 连接请求由为数不多的几个仅包含一个线程的进程 worker 以高效的回环 (run-loop) 机制进行处理, 而每个 worker 可以并行处理数千个的并发连接及请求.
Nginx 工作原理
Nginx 会按需同时运行多个进程: 一个主进程 (master) 和几个工作进程 (worker), 配置了缓存时还会有缓存加载器进程(cache loader) 和缓存管理器进程 (cache manager) 等. 所有进程均是仅含有一个线程, 并主要通过 "共享内存" 的机制实现进程间通信. 主进程以 root 用户身份运行, 而 worker,cache loader 和 cache manager 均应以非特权用户身份运行.
在高连接并发的情况下, Nginx 是 Apache 服务器不错的替代品
Nginx 安装非常的简单 , 配置文件非常简洁(还能够支持 perl 语法),Bugs 非常少的服务器: Nginx 启动特别容易, 并且几乎可以做到 7*24 不间断运行, 即使运行数个月也不需要重新启动. 你还能够 不间断服务的情况下进行软件版本的升级 .
Nginx 的诞生主要解决 C10K 问题
最后我们从各自使用的多路复用 IO 模型来分析:
select 模型:(apache 使用, 由于受模块等限制, 用的不多)
单个进程能够 监视的文件描述符的数量存在最大限制
select()所维护的 存储大量文件描述符的数据结构 , 随着文件描述符数量的增长, 其在用户态和内核的地址空间的复制所引发的开销也会线性增长
由于网络响应时间的延迟使得大量 TCP 连接处于非活跃状态, 但调用 select()还是会对 所有的 socket 进行一次线性扫描 , 会造成一定的开销
poll:poll 是 unix 沿用 select 自己重新实现了一遍, 唯一解决的问题是 poll 没有最大文件描述符数量的限制
epoll 模型:(nginx 使用)
epoll 带来了两个优势, 大幅度提升了性能:
基于事件的就绪通知方式 ,select/poll 方式, 进程只有在调用一定的方法后, 内核才会对所有监视的文件描述符进行扫描, 而 epoll 事件通过 epoll_ctl()注册一个文件描述符, 一旦某个文件描述符就绪时, 内核会采用类似 call back 的回调机制, 迅速激活这个文件描述符, epoll_wait()便会得到通知
调用一次 epoll_wait()获得就绪文件描述符时, 返回的并不是实际的描述符, 而是一个代表就绪描述符数量的值, 拿到这些值去 epoll 指定的一个数组中依次取得相应数量的文件描述符即可, 这里使用内存映射 (mmap) 技术, 避免了复制大量文件描述符带来的开销
当然 epoll 也有一定的局限性, epoll 只有 Linux2.6 才有实现 , 而其他平台都没有, 这和 apache 这种优秀的跨平台服务器, 显然是有些背道而驰了.
简单来说 epoll 是 select 的升级版, 单进程管理的文件描述符没有最大限制. 但 epoll 只有 linux 平台可使用. 作为跨平台的 Apache 没有使用
来源: http://server.51cto.com/sOS-570144.htm