Nginx
序言
Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发,最初供俄国大型的入口网站及搜寻引擎Rambler(俄文:Рамблер)使用。 其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页伺服器中表现较好.目前中国大陆使用nginx网站用户有:新浪、网易、 腾迅、多米音乐等,另外知名的微网志Plurk也使用nginx。
商业徽标:
Nginx 是国外己经开始流行的一款web服务器,中国大陆使用量也在逐年增加,它是一款开源项目svn://svn.nginx.org/nginx。据w3techs网站调查结果显示,从2011年年初市场份额为5.9%截止到2011年12月1日市场份额为10.3%.其中apache市场份额为66.4%同比下价0.6%。nginx成为2011增长最快的web服务器,远超liteSpeed。
个人最早接触的nginx版本为nginx-0.7.69版本,该版本在当时己经很稳定,处理并发的能力更是相比同类型的服务器显示出无与伦比的魅力。
关于超级负载均衡
超级负载均衡旨在为解决服务不断扩展、机器不断增多、机器性能差异等问题,以增强系统的稳定性,自动分配请求压力。算法实现了多个模型和均衡策略,能通过配置实现随机、轮询、一致hash等。同时也能实现跨机房的相关分配。现已经在多个系统中使用。
现有系统中存在的问题:
1. 慢连接、瞬时访问慢。
场景一:
如果后端新增加机器,cache命中率低,因此响应速度慢,但是能连接上且不超时。如果ui持续访问就会把ui夯住。
场景二:
如果后端模块某一台机器响应较慢。如果前端持续访问就会被夯住。
2. 死机。
场景一:
能断断续续响应请求,不过速度很慢。造成ui夯住。
3. 混合部署。
场景一:
多个模块在同一机器上,项目影响。
4. 机器权重。
场景一:
老机器,性能差;新机器,性能彪悍。因此他们应该承载不同的压力。
5. 跨机房冗余。
场景一:
后端对cache依赖很高的模块,因为采用的是一致hash算法,如果挂掉一台机器,对另外的机器cache命中率冲击很大。因此希望将对这个机器的请求均衡到另外一个机房。
6. php和c使用同样的策略。
现在php和c希望能使用的策略实际上是有很大的一致。为了避免重复开发,php和c希望采用同样的负载均衡库。
要解决的问题:
设计思路:
1. 根据均衡策略计算出的均衡值对Server进行逆序排序。
2. 负载选择。对步骤1排序后的Server按以下顺序进行选择:
a、按连接失败概率进行选择。
注:横轴代表失败次数,纵轴代表选择的概率。
Cconn:一段区间内失败次数
f(Cconn):连接概率,取值范围在(0,100]
b、按健康状态选择。
整个模型基于服务处理时间的收敛性。
分析:
1) 如果机器状态良好,则平均处理时间会保持在一个稳定水平;即使是小波动,也会较快平稳在一个状态。
2) 如果机器开始出现问题,处理时间会开始增长。如果增长持续超过一段时间,则说明有可能会影响服务;如果一段时间后稳定了,说明对请求没有太多影响。
f(healthy):机器健康状态,取值范围[0,1]
select(healthy):机器选择概率,取值范围[R,1]
c、如果所有机器都没选中,则随机选择一台机器进行服务。
3. 机器流量均分。
不同的机器处理能力是不一样的。当按照步骤2选择了某台机器,需要将其他处理时间为他的1/T(T>=2)的机器也选取出来,将部分压力分给对应的机器。
设k台机器的处理时间分别是t1, t2,…,tk, 选中的机器id=i,比该机器处理能力高的机器时间分别为p1,p2,..,pr, (其中pj × T <= ti)。设一段时间总访问量为Y,每台机器理论上的访问量应该为Vg=Y/k。而实际的Vr=Y/(ti * (1/t1+1/t2+…+1/tk))。则应该分出Vg-Vr的流量给pj。pj的流量比例为1/p1:1/p2:…:1/pr
算法设计:
A、均衡算法
1. 一致hash算法。
将每个server的ip和port加上balance_key三者做字符串拼接后,做md5签名。
value(server) = md5(server_ip + server_port + balance_key)
2. 随机算法。
value(server) = random();
3. 轮询算法。
value(server) =((server.id – (rounds % server_count)) + server_count) % server_count
4. 多个选一算法。
rank初始化为1, 如果默认的server失败,则rank+1
value(server) =((server.id – (rank % server_count)) + server_count) % server_count
B、负载算法
1. 连接状态算法。
a、对每一个server开辟一个状态队列。bool queue[K] 用来统计失败次数。每次有坏状态进队,计数加一。如果有坏状态出队,则计数减一。
b、按照f(Cconn)公式计算出选择概率。
c、利用rand()%100是否在[0,f(Cconn)]来决定是否选择该机器。
2. 健康状态算法。
a、每台机器维持一个一秒钟内的处理时间T和次数C。
b、当一秒过去以后,将T、C计算为平均处理时间R。
c、每M秒,统计每台机器最近一段时间的平均处理时间, 按照公式select(healthy)算出选择概率。
d、利用rand()%100是否在[0, select(healthy)*100]来决定是否选择该机器。
C、流量均分
按照策略选出满足要求的机器,按照流量均分公式进行流量分配。
分配时按照balance_key+server方式和random()来分配机器, 尽量保证请求落在同一台机器。
概序
HTTP基础功能:
· 处理静态文件,索引文件以及自动索引;
· 反向代理加速(无缓存),简单的负载均衡和容错;
· FastCGI,简单的负载均衡和容错;
· 模块化的结构。过滤器包括gzipping, byte ranges, chunked responses, 以及 SSI-filter 。在SSI过滤器中,到同一个 proxy 或者 FastCGI 的多个子请求并发处理;
· SSL 和 TLS SNI 支持;
IMAP/POP3 代理服务功能:
· 使用外部 HTTP 认证服务器重定向用户到 IMAP/POP3 后端;
· 使用外部 HTTP 认证服务器认证用户后连接重定向到内部的 SMTP 后端;
· 认证方法:
· POP3: POP3 USER/PASS, APOP, AUTH LOGIN PLAIN CRAM-MD5;
· IMAP: IMAP LOGIN;
· SMTP: AUTH LOGIN PLAIN CRAM-MD5;
· SSL 支持;
· 在 IMAP 和 POP3 模式下的 STARTTLS 和 STLS 支持;
支持的操作系统:
· FreeBSD 3.x, 4.x, 5.x, 6.x i386; FreeBSD 5.x, 6.x amd64;
· Linux 2.2, 2.4, 2.6 i386; Linux 2.6 amd64;
· Solaris 8 i386; Solaris 9 i386 and sun4u; Solaris 10 i386;
· MacOS X (10.4) PPC;
· windows 编译版本支持 windows 系列操作系统;
结构与扩展:
· 一个主进程和多个工作进程,工作进程运行于非特权用户;
· kqueue (FreeBSD 4.1+), epoll (Linux 2.6+), rt signals (Linux 2.2.19+), /dev/poll (Solaris 7 11/99+), select, 以及 poll 支持;
· kqueue支持的不同功能包括 EV_CLEAR, EV_DISABLE (临时禁止事件), NOTE_LOWAT, EV_EOF, 有效数据的数目,错误代码;
· sendfile (FreeBSD 3.1+), sendfile (Linux 2.2+), sendfile64 (Linux 2.4.21+), 和 sendfilev (Solaris 8 7/01+) 支持;
· 输入过滤 (FreeBSD 4.1+) 以及 TCP_DEFER_ACCEPT (Linux 2.4+) 支持;
· 10,000 非活动的 HTTP keep-alive 连接仅需要 2.5M 内存。
· 最小化的数据拷贝操作;
其他HTTP功能:
· 基于IP 和名称的虚拟主机服务;
· Memcached 的 GET 接口;
· 支持 keep-alive 和管道连接;
· 灵活简单的配置;
· 重新配置和在线升级而无须中断客户的工作进程;
· 可定制的访问日志,日志写入缓存,以及快捷的日志回卷;
· 4xx-5xx 错误代码重定向;
· 基于 PCRE 的 rewrite 重写模块;
· 基于客户端 IP 地址和 HTTP 基本认证的访问控制;
· PUT, DELETE, 和 MKCOL 方法;
· 支持 FLV (Flash 视频);
· 带宽限制;
实验特性:
· 内嵌的 perl
· 通过 aio_read()/aio_write() 的套接字工作的实验模块,仅在 FreeBSD 下。
· 对线程的实验化支持,FreeBSD 4.x 的实现基于 rfork()
为什么选择Nginx
Nginx 是一个很牛的高性能Web和反向代理服务器, 它具有有很多非常优越的特性:
· 在高连接并发的情况下,Nginx是Apache服务器不错的替代品: Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50,000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型.
· Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多.
· 作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器), Last.fm 描述了成功并且美妙的使用经验.
· Nginx 是一个 [#installation 安装] 非常的简单 , 配置文件 非常简洁(还能够支持perl语法), Bugs 非常少的服务器: Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够 不间断服务的情况下进行软件版本的升级 .
安装Nginx
预编译版
Linux 和 BSD 的预编译包
大部分 Linux 发行版和 BSD 衍生版的源里都有 Nginx,使用通常安装其他软件的方式即可安装(在 Debian 上用 apt-get,Gentoo 上用 emerge,FreeBSD 上用 ports,等等)。
请注意这些包通常不是最新版本。如果你想使用最新功能和 Bug 修复,建议从源码编译安装(实际上,编译安装也相当简单)。
Win32 预编译包
现在nginx官方已经发布了官方版的nginx/Win32了,欢迎大家使用。在先前Kevin Worthington 负责维护一个 Windows 的最新预编译版分支,如果您已经习惯了使用这个版本也可以选择使用这个版本的。
源代码发布
Nginx 有两个版本:稳定版 (1.0.x), 和 历史稳定版 (0.8.x)。同时,我们在svn中也提供开发版。开发版分支会较快获得新功能和缺陷修复,但同时也可能遇到新的缺陷。一旦更新稳定下来,就会被加入稳定版分支。然而新功能不一定会被加到旧的稳定版中去。
作为生产环境,通常建议使用稳定版,但其实开发版本也相当稳定。
如果您的网站不是基于Fcgi,建议使用开发版。请参考
http://wiki.nginx.org/NginxFaq#Is_it_safe_to_use_the_development_branch_in_production.3F
所有版本下载地址:http://nginx.org/en/download.html
从源代码编译 Nginx
把源码解压缩之后,在终端里运行如下命令:
./configure
make
sudo make install
默认情况下,Nginx 会被安装在 /usr/local/nginx。通过设定编译选项,你可以改变这个设定。
Nginx/Win32 安装
为了安装Nginx/Win32,需先下载它。然后解压之,然后运行即可。下面以C盘根目录为例说明下:
cd C:
cd C:\nginx-0.7.69 start nginx
Nginx/Win32是运行在一个控制台程序,而非windows服务方式的。服务器方式目前还是开发尝试中,Nginx/Win32可以使用以下开关来管理它:
Nginx -s stop 快速关闭Nginx,可能不保存相关信息,并迅速终止web服务。(quick exit)
Nginx -s quit 平稳关闭Nginx,保存相关信息,有安排的结束web服务。(graceful exit)
Nginx -s reload 因改变了Nginx相关配置,需要重新加载配置而重载。(changing configuration,start a new worker,quitting an old worker gracefully.)
Nginx -s reopen 重新打开日志文件。(reopenging log files)
性能比较
一份从网上搜到的性能测试比较使用的工具为:loadrunner。
Loaderunner为测试并发的一款软件工具,具体使用可以请教测试人员。
关于“传输率”这幅图的纵坐标的意义,100000 相当于 100MB/sec,也就是常说的百兆网络(忽略 CSMA/CD 造成的损失),而常说的千兆网络,经过测试,大概在400000~500000之间,换句话来说,如果nginx服务器的出口带宽是百兆网络的话,瓶颈在 网络而不是nginx。
针对第二组图片也是有几个地方需要解析一下的:
生产环境的成绩应该是在蓝线和红线之间的区间,这个就不用再解析了吧。
“Logest Response Time” 实际上取的是能完成所有请求中的99%时的时间,这样可以屏蔽一些误差。
随着压力的增加,响应时间的飙升是可以预见的,但是多少才算是一个可接受范围呢?在2009系统架构师大会腾讯的邱跃鹏在《海量SNS网站的柔性运营》中的发言提到的“用户速度体验的1-3-10原则”:
可以简单的认为:如果以3秒的响应时间作为标准的话,nginx能应付不超过10000的并发连接数,如果以10秒响应时间作为标准的话,nginx能应付15000以下个并发连接,当然,可能场合不同,您的用户连0.3秒都无法忍受,这个就要另说咯。
3种WEB服务器的比较:
server | Apache | Nginx | Lighttpd |
Proxy代理 | 非常好 | 非常好 | 一般 |
Rewriter | 好 | 非常好 | 一般 |
Fcgi | 不好 | 好 | 非常好 |
热部署 | 不支持 | 支持 | 不支持 |
系统压力比较 | 很大 | 很小 | 比较小 |
稳定性 | 好 | 非常好 | 不好 |
安全性 | 好 | 一般 | 一般 |
技术支持 | 非常好 | 很少 | 一般 |
静态文件处理 | 一般 | 非常好 | 好 |
Vhosts虚拟主机 | 支持 | 不支持 | 支持 |
反向代理 | 一般 | 非常好 | 一般 |
Session sticky | 支持 | 不支持 | 不支持 |
l 静态页面 搜狐首页
LIGHTTPD
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 64 | 60 | 462.75 | 21.6 |
100000/200 | 67 | 60 | 312.07 | 32.4 |
100000/500 | 83 | 60 | 137.24 | 72.8 |
100000/1000 出现错误丢包 | 94 | 60 | 126.6 | 78.9 |
NGINX
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 34.6 | 140 | 943.66 | 10.597 |
100000/200 | 35.6 | 110 | 924.32 | 10.818 |
100000/500 | 34.3 | 110 | 912.68 | 10.956 |
100000/1000 | 37 | 160 | 832.59 | 12.106 |
APACHE
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 40.6 | 170 | 690.72 | 14.47 |
100000/200 | 41.1 | 180 | 685.39 | 14.59 |
100000/500 | 42.3 | 190 | 633.64 | 15.78 |
100000/1000 | 43.1 | 200 | 547.53 | 18.26 |
l 动态页面 内部社区首页
LIGHTTPD
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
1000/100 | 50 | 200 | 33.54 | 29.816 |
1000/200 | 52 | 210 | 30.43 | 32.858 |
1000/500 | 54 | 230 | 25.79 | 38.76 |
1000/1000 | 62 | 250 | 24.83 | 40.28 |
NGINX
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
1000/100 | 53.8 | 250 | 83.12 | 12.305 |
1000/200 | 55.8 | 250 | 74.05 | 13.504 |
1000/500 | 56 | 260 | 58.99 | 16.951 |
1000/1000 | 58 | 260 | 43.41 | 23.347 |
APACHE
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 60 | 200 | 27.37 | 36.541 |
100000/200 | 61 | 220 | 23.82 | 41.981 |
100000/500 | 73 | 150 | 20.59 | 48.562 |
100000/1000 | 53 | 200 | 27.18 | 36.796 |
l PHPINFO函数页
LIGHTTPD
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 45 | 20 | 168.06 | 59.504 |
100000/200 | 47 | 22 | 140.64 | 71.103 |
100000/500 | 49 | 24 | 52.80 | 189.386 |
100000/1000 | 在请求到4840时测试测试程序死掉 |
NGINX
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 70 | 120 | 143.46 | 69.706 |
100000/200 | 72 | 130 | 140.57 | 71.140 |
100000/500 | 73 | 150 | 135.87 | 73.601 |
100000/1000 | 77 | 160 | 132.18 | 75.657 |
APACHE 出现丢包
n/-c(ab参数) | cpu% | Mem | RequestsperSecond | Time taken for tests |
100000/100 | 70 | 180 | 245.73 | 40.694 |
100000/200 | 72 | 190 | 245.79 | 40.684 |
100000/500 | 75 | 200 | 241.29 | 41.443 |
100000/1000 | 77 | 220 | 236.74 | 42.239 |