1.1 目的
测试Nginx在Linux下的性能,优点,研究Nnginx在Linux下如何配置,优化。
1.2 背景
Nginx专为性能优化而开发,性能是最重要的考量,实现上非常注重效率。它支持内核Epoll模型,能经受高负载的考验,有报告表明能支持高达50000个并发连接数。Nginx具有很高的稳定性。其他HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。Nginx支持热部署。它的启动特别容易,并且几乎可以做到7×24不间断运行,即使运行数个月也不需要重新启动。
1.3 定义
Epoll模型:Epoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。
负载均衡:负载均衡 (Load Balancing) 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
1.4 参考资料
Nginx维基中文网
Nginx应用技术指南 V1.5
实战Nginx取代Apache的高性能服务器
2. 调研过程
2.1 Nginx在Ubuntu下的搭建与配置
2.1.1 Ubuntu的安装与配置
Win Xp下,用虚拟机VitualBox安装的Ubuntu10.10,虚拟机的配置是512M内存,8G硬盘。
2.1.2 Nginx在Ubuntu下的安装
Nginx在Ubuntu下有两种安装方法:
1.通过apt-get直接安装。
2.通过下载Nginx源码编译安装。
2.1.2.1 APT安装
通过在终端输入命令获得Nginx,打开终端,输入命令,这里不需要版本号,apt-get会自动选择最新的。
sudo apt-get install nginx
2.1.2.2 编译安装
因为Nginx不支持动态链接模块,所以安装模块或者安装第三方模块需要将模块代码与Nginx源代码重新编译。
依赖的程序
先安装以下三个程序:
1. gzip module requires zlib library
2. rewrite module requires pcre library
- ssl support requires openssl library
以下是各个程序的下载的网址:
- http://www.gzip.org/
- http://www.pcre.org/
- http://www.openssl.org/
下载下来后通过向终端输入以下命令安装:
tar xvf *.tar
cd gzip-1.2.4
./configure
make
make install
在Nginx官方网站上下载所需的Nginx版本的源码压缩包。解压源码包后,然后具体命令如下:
tar xvf *.tar
./configure
make
make install
默认的安装配置是/usr/local/nginx
2.1.2.3两者之间的区别
Nginx不支持动态链接模块,通过apt安装的Nginx只是具备默认的定制的模块,如果需要增加删减模块或使用第三方的模块,建议是用编译安装。
2.2 Nginx的模块
Nginx主要功能都是通过模块来实现的。
Nginx核心模块。
Nginx标准HTTP模块:这些模块默认会全部编译进Nginx,除非手工指定某个模块在configure时排除。
Nginx可选HTTP模块(Optional HTTP Modules): 如果要使用这些模块,则必须在编译时指定相关的编译参数。
Nginx邮件模块(Mail modules)
第三方模块(3rd Party Modules): 这些模块虽然没有正式被官方支持,但是可以帮助用户完成不少的功能。使用过程中请自行承担遇到的问题。
2.3 Nginx的配置文件
Nginx的配置文件默认在Nginx程序安装目录的conf目录下,文件名为nginx.conf,主要结构由events,http,server构成,如图3。
图3.nginx.conf的结构
2.4 Nginx的负载均衡
用于负载均衡的模块为HTTP Upstream模块,该模块是默认添加的,不需要手动配置。
负载均衡有5种算法用来指定当有请求过来时分配哪一个服务器。1.轮询算法 2.ip_hash 3.weight 4.fair(第三方模块) 5.url_hash(第三方模块)
以下是配置的weight算法的负载均衡
user www www ;
worker _processes 1;
events {
use epoll ;
worker_connections 51200 ;
}
http{
include mime.types;
default_type application/octet-stream ;
sendfile on ;
keepalive_timeout 65 ;
upstream sever_poll{
sever 192.168.71.41:88 weight=1 max_fails=3 fail_timeout=4s;
sever 192.168.71.41:89 weight=10 max_fails=3 fail_timeout=4s ;
}
sever{
listen 80 ;
sever_name localhost ;
location /{
proxy_pass http://sever_pool ;
}
error_page 500 502 503 504 /50x.html ;
location = /50x.html {
root html ;
}
}
}
这个配置中在192.168.71.41上建了2个服务器,通过设置不同的端口,让其成为负载服务器。通过设置权重算法来实现负载均衡。试验结果表明每向服务器发送11次请求,192.168.71.41:88命中1次,192.168.71.41:89命中10次。
2.5 Nginx优化
2.5.1 Nginx 处理器优化
首先先查看有多少处理器,在控制台输入
cat /proc/cpuinfo
如果processor显示为3,则处理器个数为4个。如果处理器为4个的话,那应该这样写,如下:
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000 ;
第一句指定进程的个数。
第二句只是每个进程所分配的处理器。进程1分配到0001处理器,假定为cpu1。以此类推进程2分配到0010处理器,cpu2。进程3分配到0100处理器,cpu3。进程4分配到1000处理器,cpu4。
2.5.2 Nginx传输优化
在某一台图片服务器上的配置:
gzip on;
gzip_buffers 4 16k; 设置gzip的缓存
gzip_comp_level 9; 设置压缩比率
gzip_min_length 1k; 设置最小压缩值
gzip_proxied any; 设置代理时是否进行压缩
gzip_types text/plain application/x-javascript text/css application/xml;
2.5.3 Nginx 的缓存设置
Nginx从0.7.48版本开始,支持了类似Squid的缓存功能。这个缓存是把URL及相关组合当作Key,用md5编码哈希后保存在硬盘上,所以它可以支持任意URL链接,同时也支持404/301/302这样的非200状态码。虽然目前官方的Nginx Web缓存服务只能为指定URL或状态码设置过期时间,不支持类似Squid的PURGE指令,手动清除指定缓存页面,但是,通过一个第三方的Nginx模块,可以清除指定URL的缓存。
2.5.4 Nginx编译安装优化
在编译Nginx时,默认以debug模式进行,而在debug模式下会插入很多跟踪和ASSERT之类的信息,编译完成后,一个Nginx要有好几兆字 节。在编译前取消Nginx的debug模式,编译完成后Nginx只有几百千字节,因此可以在编译之前,修改相关源码,取消debug模式,具体方法如 下:
在Nginx源码文件被解压后,找到源码目录下的auto/cc/gcc文件,在其中找到如下几行:
#debug
CFLAGS=” $CFLAGS –g”
将其注释或者删除。
2.5.5 Nginx为特定的CPU指定CPU类型的编译优化
在编译Nginx时,默认的GCC编译参数是“-O”,要优化GCC编译,可以使用以下两个参数:
--with-cc-opt='-O3'
--with-cpu-opt=CPU #为特定的 CPU 编译,有效的值包括:pentium, pentiumpro, pentium3, pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64
要确定CPU类型,可以通过如下命令:
[root@localhost home]#cat /proc/cpuinfo | grep "model name"
2.5.6 利用TCMalloc优化Nginx的性能
TCMalloc的全称为Thread-Caching Malloc,是谷歌开发的开源工具“google-perftools”中的一个成员。与标准的glibc库的malloc相比,TCMalloc库在 内存分配效率和速度上要高很多,这在很大程度上提高了服务器在高并发情况下的性能,从而降低系统负载。下面简单介绍如何为Nginx添加TCMalloc 库支持。要安装TCMalloc库,需要安装libunwind(32位操作系统不需要安装)和google-perftools两个软件包,libunwind 库为基于64位CPU和操作系统的程序提供了基本函数调用链和函数调用寄存器功能。下面介绍利用TCMalloc优化Nginx的具体操作过程:
2.5.6.1安装libunwind库
可以从http://download.savannah.gnu.org/releases/libunwind下载相应的libunwind版本,这里下载的是libunwind-0.99-alpha.tar.gz,安装过程如下:
[root@localhost home]#tar zxvf libunwind-0.99-alpha.tar.gz
[root@localhost home]# cd libunwind-0.99-alpha/
[root@localhost libunwind-0.99-alpha]#CFLAGS=-fPIC ./configure
[root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC
[root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC install
2.5.6.2安装google-perftools
可以从http://google-perftools.googlecode.com下载相应的google-perftools版本,这里下载的是google-perftools-1.8.tar.gz,安装过程如下:
tar zxvf google-perftools-1.8.tar.gz
cd google-perftools-1.8/
./configure
make && make install
echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
ldconfig
至此,google-perftools安装完成。
2.5.6.3 重新编译Nginx
为了使Nginx支持google-perftools,需要在安装过程中添加“–with-google_perftools_module”选项重新编译Nginx,安装代码如下:
./configure \ >--with-google_perftools_module --with-http_stub_status_module --prefix=/opt/nginx
make
make install
到这里Nginx安装完成。
2.5.6.4 创建线程目录
为google-perftools添加线程目录创建一个线程目录,这里将文件放在/tmp/tcmalloc下,操作如下:
mkdir /tmp/tcmalloc
chmod 0777 /tmp/tcmalloc
2.5.6.5 修改配置文件
修改Nginx主配置文件,修改nginx.conf文件,在pid这行的下面添加如下代码:
pid logs/nginx.pid;
google_perftools_profiles /tmp/tcmalloc;
接着,重启Nginx,完成google-perftools的加载。
2.5.6.6验证运行状态
为了验证google-perftools已经正常加载,通过如下命令查看:
[root@ localhost home]# lsof -n | grep tcmalloc
nginx 2395 nobody 9w REG 8,8 0 1599440 /tmp/tcmalloc.2395
nginx 2396 nobody 11w REG 8,8 0 1599443 /tmp/tcmalloc.2396
nginx 2397 nobody 13w REG 8,8 0 1599441 /tmp/tcmalloc.2397
nginx 2398 nobody 15w REG 8,8 0 1599442 /tmp/tcmalloc.2398
由于在Nginx配置文件中,设置worker_processes的值为4,因此开启了4个Nginx线程,每个线程会有一行记录。每个线程文件后面的数字值就是启动的Nginx的PID值。
至此,利用TCMalloc优化Nginx的操作完成。
2.6 Linux内核优化
内核参数的优化,主要是在Linux系统中针对Nginx应用而进行的系统内核参数优化,常见的优化参数值如下。
下面给出一个优化实例以供参考:
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_syncookies = 1
net.core.somaxconn = 262144
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
将上面的内核参数值加入/etc/sysctl.conf文件中,然后执行如下命令使之生效:
/sbin/sysctl –p
下面是对实例中选项的含义进行介绍:
net.ipv4.tcp_max_tw_buckets参数用来设定timewait的数量,默认是180000,这里设为6000。
net.ipv4.ip_local_port_range选项用来设定允许系统打开的端口范围。
net.ipv4.tcp_tw_recycle选项用于设置启用timewait快速回收.
net.ipv4.tcp_tw_reuse选项用于设置开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接。
net.ipv4.tcp_syncookies选项用于设置开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies进行处理。
net.core.somaxconn选项默认值是128, 这个参数用于调节系统同时发起的tcp连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此,需要结合并发请求数来调节此值。
net.core.netdev_max_backlog选项表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目。
net.ipv4.tcp_max_orphans选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数 字,孤立连接将立即被复位并打印出警告信息。这个限制只是为了防止简单的DoS攻击。不能过分依靠这个限制甚至人为减小这个值,更多的情况是增加这个值。
net.ipv4.tcp_max_syn_backlog选项用于记录那些尚未收到客户端确认信息的连接请求的最大值。对于有128MB内存的系统而言,此参数的默认值是1024,对小内存的系统则是128。
net.ipv4.tcp_synack_retries参数的值决定了内核放弃连接之前发送SYN+ACK包的数量。
net.ipv4.tcp_syn_retries选项表示在内核放弃建立连接之前发送SYN包的数量。
net.ipv4.tcp_fin_timeout选项决定了套接字保持在FIN-WAIT-2状态的时间。默认值是60秒。正确设置这个值非常重要,有时候即使一个负载很小的Web服务器,也会出现因为大量的死套接字而产生内存溢出的风险。
net.ipv4.tcp_keepalive_time选项表示当keepalive启用的时候,TCP发送keepalive消息的频度。默认值是2(单位是小时)。
3.调研结果评估
3.1 总体评估
Nginx在Linux下的环境搭建比在windows下搭建复杂,但是在功能和性能上有很大的区别,依靠着Linux的自身的开源环境,Nginx的性能也有了大大的提高。
3.2 功能评估
各项功能都能正常使用,在Linux下通过扩展第三方模块,功能上比windows环境下搭建Nginx要灵活。
3.3 可用性评估
通过对Configure文件的修改,达到对Nginx进行操作,使用方便。
3.4 性能评估
在Linux下使用的EPOLL模型,比Windows下使用SELECT模型要好的多。同时在Linux下能对源代码,以及编译环境的及时的优化,性能上比Windows下搭建Nginx环境要高很多。
实际测试:
根据OSSP10接口性能测试报告,单接口架构下:
400路并发下性能最佳,TPS测试值的均值为1328,最大值为1846;响应时间测试值的均值为191ms。400路以上,TPS不再增加,响应时间增长,1000路并发时,响应时间测试值均值为562ms,最大值为2s左右。
Nginx+接口架构下:
400路并发下性能最佳,TPS测试值得均值为1792,最大值为2477,响应时间测试值均值为120ms;之后随着并发用户数的增加不再增长,1000路并发下,持续不到8分钟,事务成功率迅速降低,TPS迅速下降;因超时出现失败事务,最大的响应时间在1000路并发时达到90s,此时成功率为99.567%。