Tengine/Nginx性能优化及杂谈

  • A+
所属分类:Nginx web服务
  • 本文源自 红塔山lvs, 于2017-12-2401:56:01,由 整理发表,共 7651 字。
摘要

编辑于 2016-07-22 的关于Tengine/Nginx性能优化的经验之谈。

谷歌、度娘搜索Nginx优化,能搜索出很多的文章,动不动就几万并发,十万并发,看着好像真是那么回事似的。

从使用Tengine的过程中,对Tengine/Nginx的优化,我个人认为Tengine的优化是脱离不开使用它的环境及部署结构的,单说优化 Tengine的意义并不大,况且每家公司的业务各不相同,所以优化不是简单的事情。即便如此,我总结了下,从以下几个方便入手浅谈下 Tengine/Nginx的性能优化。本文以Tengine为主,Nginx大部分都适用。

1、网络

带宽

一个需要支持1万并发且平均页面内容在100KB的情况下,就需要大概1G的带宽,如果带宽只有100M,需要支持这样的场景无论如何也是不可能的。更好的带宽可以支持更高的并发

路由

现在的IDC运营商有很多,越小的运营商在路由优化上就不怎么样,例如在对IDC进行测试的时候,大部分运维使用ping来测试机房的网络质量,这种测试 其实是点到点的测试,中间大网的情况就测试不到。在使用mtr进行测试的时候,可以看到每一跳的延迟及路由,很多时候会发现浮动路由。这种情况下网络质量 一定不好。最好通过mtr对机房提供的IP连续进行一周的测试,路径都比较稳定的时候这样的机房值得选择。

2、硬件

CPU

一般情况下作为Tengine/Nginx的应用,CPU的频率我认为对性能影响还是较小的,但是核心数对于Tengine/Nginx而言确实很有用, 更多的核心数外加HT技术,可以让Tengine/Nginx运行更多的worker,从而提升Tengine/Nginx的负载能力

内存

内存的容量直接对Tengine/Nginx可承载的连接数有影响(主要指ESTAB连接)。另外大容量的内存在结合tmpfs进行合理使用的话,可以作为Tengine/Nginx的各种temp目录及各种缓存目录,降低对磁盘IO的消耗

网卡

目前在互联网公司DELL的服务器应该是用的最多的了,而且在用户没有特殊需求的时候,配置的网卡通常是Broadcom BCM57XX的,这种网卡比较便宜所有在处理小包的时候,带宽利用率不高,且流量大的时候会出现大量丢包。在Tengine/Nginx的机器上还是推 荐使用Intel X350I QP的网卡,在使用最新的网卡驱动后,可以对网卡做出更多性能控制(X350默认的RSS队列最大为8个)

磁盘

磁盘的IO能力个人认为在硬件里的比重不高,在拿Tengine/Nginx作为专用缓存服务器的时候,使用SATA SSD或者PCIe-SSD卡时可以作为缓存存放的目录路径。一般Intel S3710 800G的大概7000左右,同容量宝存的800G PCIe-SSD大约1.5W。

3、系统

TCP/IP协议栈

CLOSE_WAIT与TIME_WAIT

这两种连接状态是Web服务器中大家最关心的也是最让大家头疼的,虽然很多的博客里说现在服务器内存大,这种连接达到几万、几十万时对内存的消耗不是问题 不用去理会,但是在一些场景中可能会对应用造成很大的影响。例如在我们的业务中出现CLOSE-WAIT状态时,是数据库有长事务执行时导致Resin出 现了CLOSE-WAIT连接,当这种连接数高于10个时,应用就会打开慢直到应用打不开。所以需要对其进行优化。尽量避免系统中出现过多的这两种连接。

当Tengine/Nginx反向代理后端服务器的时候,Tengine所在的服务器上会出现TIME-WAIT(跟后端服务器断开后产生的状态)以及 CLOSE-WAIT(客户端断开后产生的状态)的连接,一般为了减少Tengine/Nginx与后端服务器通信时造成的TIME-WAIT连接,主要 需要如下的配置,例如:

配置一

upstream example {

        server 192.168.0.1:8080;

        keepalive 4;

}

server{

        listen 80 backlog=2048;

        server_name www.example.com;

        location = /favicon.ico {

                error_page 404 = 200;

                log_not_found off;

                access_log off;

        }

        location = /robots.txt {

                error_page 404 = 200;

                log_not_found off;

                access_log off;

        }

        location / {

                include proxy_opt.conf;

                proxy_http_version 1.1;

                proxy_set_header Connection "";

                proxy_pass      http://example;

        }

}

配置二

server{

        listen 80 backlog=2048;

        server_name www.example.com;

        location = /favicon.ico {

                error_page 404 = 200;

                log_not_found off;

                access_log off;

        }

        location = /robots.txt {

                error_page 404 = 200;

                log_not_found off;

                access_log off;

        }

        location / {

                include proxy_opt.conf;

                proxy_pass      http://192.168.0.1:8080;

        }

}

两种配置,都可以实现www.example.com的访问,区别在于配置一因为使用upstream且在upstream里配置了keepalive连 接,在压力较大的时候Nginx与后端server之间的CLOSE-WAIT以及TIME-WAIT将非常少,因为有长连接。而配置二是直接 proxy_pass,在压力大的时候CLOSE-WAIT和TIME-WAIT的数量将比较多,在这种情况下,容易产生孤儿连接,孤儿连接一般占用内存 约64K且为不可交换内存(可参考内核文档)。在Tengine中不光可以在upstream中配置与upstream的长连接,还支持长连接超时参数。 (此处估计有人说优化TCP/IP协议栈就可以降低CLOSE-WAIT和TIME-WAIT的连接数了,真的吗?你去试试就知道了。)

除了在Nginx上启用upstream来减少CLOSE-WAIT和TIME-WAIT的连接数外,还有2种方式:

a)在/etc/sysctl.conf中将net.ipv4.tcp_max_tw_buckets的值改为0,可以快速释放TIME-WAIT连接(此法比较暴力,但在系统负载比较高时比较好使,有点像Haproxy中的option forceclose

b)编辑kernel中include/net/tcp.h



#define TCP_TIMEWAIT_LEN (60*HZ)

修改为

#define TCP_TIMEWAIT_LEN (5*HZ)

重新编译内核

4、Tengine本身

安装方式的选择

对于Tengine的安装,目前貌似官方只提供源码包,只能编译安装

对于Nginx的安装,可以通过在线的软件源进行在线安装,也可以源码编译安装

在线安装一般使用通用的CPU指令集对Nginx进行编译,这种方式不能很好的利用当前CPU的指令集,且配置文件、可执行文件均不能自定义安装目录。对于大规模进行批量化部署时不方便。

源码编译可以通过指定gcc的参数结合CPU的指令集对Nginx进行编译,可以充分使用CPU的指令集提升性能,且安装目录可以自定义,通过修改可执行文件的rpath还可以被fpm打包成公司专用的rpm包,适合批量部署。

对于GCC可使用的参数,可以参考GCC的官方手册

基本配置的优化

#自动设置Nginx启动的worker数量,默认是CPU的processor数(不是core数)

worker_processes auto;

#自动将Nginx的worker进程绑定到CPU的processor上,1.9.10才支持auto,Tegine默认支持

worker_cpu_affinity auto;

#设置所有worker的open files数,如不设置默认为系统ulimit -n的大小

worker_rlimit_nofile 100000;

#开启pcre jit功能,编译pcre的时候需要开启jit功能

pcre_jit on;

events{

        use epoll;

        worker_connections 8192; 每个worker的最大连接数,这个数字不光光只Nginx与Client间的连接,还包括Nginx与后端Server的连接数,配置的时候须注意 worker_rlimit_nofile>worker_connections*workers

        accept_mutex off;在访问量较大的网站上建议关闭accept_mutex机制

}

client_header_buffer_size 8k;

client_header_timeout 10;

client_body_buffer_size 256k;

client_body_timeout 10;

large_client_header_buffers 4 8k;

client_max_body_size 20m;

send_timeout 10;

keepalive_timeout 30;

keepalive_requests 5000;

reset_timedout_connection on;

log_format access

配置文件中的各种buffer

proxy_pass

proxy_connect_timeout   60;

proxy_send_timeout      60;

proxy_read_timeout      60;

proxy_buffer_size       64k;

proxy_buffers           4 64k;

proxy_busy_buffers_size 128k;

proxy_temp_file_write_size 512k;

proxy_next_upstream error timeout invalid_header http_503 http_404 http_502 http_504;

proxy_max_temp_file_size 32m;

proxy_intercept_errors  on;

fastcgi_pass

fastcgi_connect_timeout 30;

fastcgi_send_timeout 15;

fastcgi_read_timeout 15;

fastcgi_buffer_size 64k;

fastcgi_buffers 4 64k;

fastcgi_busy_buffers_size 128k;

fastcgi_temp_file_write_size 512k;

单台Tengine最大连接数估算

合理利用proxy_cache和fastcgi_cache

SO_REUSEPORT && TCP Fast Open

关于SO_REUSEPORT和TCP Fast Open的原理以及它们是做什么的,可以自行谷歌上查找

就这reuseport功能Tengine 2.1.0就支持,Nginx直到1.9.1才支持reuseport

SO_REUSEPORT特性本来是kernel 3.9以上才支持的功能,不过Red Hat在其6.5版本开始就支持该特性了,所以使用CentOS 6系列的童鞋只需要升级内核大于6.5版本的就可以使用了。

TCP Fast Open这个特性RHEL 6中并没有支持,真的需要3.7以上的内核才支持,有需要使用这个特性的童鞋可以升级内核,升级可以安装UEK内核,或者通过ELRepo安装高版本的内 核,通知需要重新编译Tengine或者Nginx用以支持TFO,另Haproxy 1.5已经支持TFO功能

合理使用tmpfs

在使用Nginx的过程中,总是会考虑使用proxy_cache,fastcgi_cache,同时也会产生各种临时文件,大多数情况下,运维工程师都 会使用物理磁盘去承担这部分工作,但这样会产生额外的IO,重要的是响应速度方面磁盘要低于内存,所以在针对各种cache,以及各种temp的情况,有 以下建议可参考:

a)用Nginx做缓存服务器

在使用1U DELL R630且内存为128G的前提条件下,如果被缓存的数据小于64G,可考虑直接使用tmpfs来作为proxy_cache或者fastcgi_cache的存储介质,当缓存数量非常大时也可以使用PCIe-SSD来做缓存的存储介质

b)将Nginx产生的临时文件放入tmpfs

本人使用的做法,将mount tmpfs的命令写入Nginx的启动脚本中。读者可自行研究,以下为自用启动脚本

注意tmpfs如果使用echo {1,2,3} > /proc/sys/vm/drop_caches是无法释放tmpfs占用的内存的,除非清空tmpfs

#! /bin/sh
# Description: Startup script for Tengine
# chkconfig: 2345 55 25
PATH=/sbin:/bin:/usr/sbin:/usr/bin
DESC="Tengine daemon"
NAME=tengine
DAEMON=/opt/websuite/tengine/sbin/nginx
CONFIGFILE=/opt/config/tengine/nginx.conf
PIDFILE=/opt/run/tengine/$NAME.pid
SCRIPTNAME=/etc/init.d/rc.tengine
TESTPATH=/opt/websuite
CACHEDIR=/opt/websuite/tengine/cache
TEMPDIR=/opt/websuite/tengine/temp
set -e
[ -x "$DAEMON" ] || exit 0
 
do_start() {
 $DAEMON -c $CONFIGFILE || echo -n "tengine already running"
}
 
do_stop() {
 $DAEMON -c $CONFIGFILE -s stop || echo -n "tengine not running"
}
 
do_reload() {
 $DAEMON -c $CONFIGFILE -s reload || echo -n "tengine can't reload"
}
 
do_mount_ramdisk() {
 mount -t tmpfs tmpfs $TEMPDIR/client -o defaults,size=32M,uid=websuite,mode=755
 mount -t tmpfs tmpfs $TEMPDIR/proxy -o defaults,size=32M,uid=websuite,mode=755
 mount -t tmpfs tmpfs $TEMPDIR/fastcgi -o defaults,size=32M,uid=websuite,mode=755
 mount -t tmpfs tmpfs $TEMPDIR/hmux -o defaults,size=32M,uid=websuite,mode=755
 mount -t tmpfs tmpfs $CACHEDIR/proxy -o defaults,size=512M,uid=websuite,mode=755
 mount -t tmpfs tmpfs $CACHEDIR/fastcgi -o defaults,size=512M,uid=websuite,mode=755
}
 
do_umount_ramdisk() {
 umount $TEMPDIR/client
 umount $TEMPDIR/proxy
 umount $TEMPDIR/fastcgi 
 umount $TEMPDIR/hmux
 umount $CACHEDIR/proxy
 umount $CACHEDIR/fastcgi
}
 
case "$1" in
 start)
 echo -n "Starting $DESC: $NAME"
 if [ $(mount|grep $TESTPATH|wc -l) -eq 0 ];then
        do_mount_ramdisk
 fi
 do_start
 echo "."
 ;;
 stop)
 echo -n "Stopping $DESC: $NAME"
 do_stop
 if [ $(mount|grep $TESTPATH|wc -l) -gt 0 ];then
        do_umount_ramdisk
 fi
 echo "."
 ;;
 reload)
 echo -n "Reloading $DESC configuration..."
 do_reload
 echo "."
 ;;
 restart)
 echo -n "Restarting $DESC: $NAME"
 do_stop
 sleep 1
 do_start
 echo "."
 ;;
 *)
 echo "Usage: $SCRIPTNAME {start|stop|reload|restart}" >&2
 exit 3
 ;;
esac
exit 0

5、Nginx常见部署场景

静态资源网站

Tengine+PHP-FPM

Tengine+Tomcat

Tengine使用hmux构建Resin集群

Tengine结合KVM构建Web集群

Haproxy/LVS+Tengine的配合使用

6、监控

Tengine基本状态输出

利用nginx-module-vts输出更多数据

7、其他

分布式缓存

缓解机器人压力

动态更新upstream

有Varnish的架构中Tengine扮演的角色

天使

发表评论

您必须登录才能发表评论!