本文目的
通过使用 2019年主流的软件技术,配置高可靠高性能的Nginx。线上运行的8核8G的单台虚拟机稳定支持 200Mb/s 持续流量没有出现服务间断、CPU飙高等情况。
本文不涉及到重新编译内核、不依赖特定硬件设备、不依赖特定网络架构、不需要使用物理机。
适用范围
本文不求标新立异,使用的是通用而有效的优化方法,适用于主流的操作系统:
- CentOS 6.7+ (已经测试和验证)
- CentOS 7.0+ (已经测试和验证)
- Ubuntu 14.04 (支持,未测试)
- Ubuntu 16.04 (已经测试和验证)
- Ubuntu 18.04 (已经测试和验证)
- Debian 8, 9, 10 (支持,未测试)
Nginx + Keepalived 一句话 介绍
常见的组合,常用来实现高可靠的4层和7层的代理服务器。
Nginx 版本推荐
Tengine 2.3.x
基于 nginx 1.15 , 阿里出品,高性能,内置官方的Stream模块可直接支持TCP代理。
不过还没有正式发布,也缺少 stream 模块的 upstream 的健康检测功能。Tengine 2.2.2
基于 nginx 1.8 , 阿里出品,高性能,支持健康检测模块,可以安装 https://github.com/yaoweibin/nginx_tcp_proxy_module 扩展支持tcp代理。OpenResty 1.15
Nginx 的 “集成打包版”,基于较新的 Nginx ,luajit 生态的扩展版。Nginx 1.15.9
官方开源版本。
以上三个版本各有千秋,目前我们线上用的是 Tengine 。
优化因素(风险由低到高)
- 操作系统
- ulimit 参数
- ip_vs 参数
- 网卡参数
- irq 软中断
- CPU 亲缘
- nginx 参数优化
- 内核启动参数
- 内核sysctl参数
- 内核版本
操作系统
推荐使用 Ubuntu 18.04、16.04 或是 CentOS 7.5+ 操作系统。
如果现在还是要坚持使用CentOS 6,总有一天也会因为内核版本老、软件版本老、不支持Docker、不支持 Systemd 等原因而主动或被动升级。再升级早享受。
irqbalance 服务可以自动绑定 cpu 负载软中断,需要内核高于 2.4 的版本。
ulimit 参数
推荐设置为 1048576
ip_vs 参数
很多文章提到,通过修改内核参数配置,重新编译内核实现 ip_vs 模块的参数优化。事实上较新的系统(包括 CentOS 6.7 及以上)完全没必要重新编译内核,仅需要配置加载参数 options ip_vs conn_tab_bits=20 即可实现。
网卡参数
关闭 gso gro tso
irq 软中断
开启 irqbalance 服务能显著减低软中断 ksoftirqd 引起的cpu负载。(内核须高于2.4版本)
nginx 流量高于 300Mb/s 时,如果发现 ksoftirqd 的 cpu 负载很高, 而且网络延迟加大,可以检查 irqbalance 服务是否开启。
CPU 亲缘
nginx 配置中,进行如下设置: worker_processes auto; worker_cpu_affinity auto;
nginx 参数优化
http 参数各种常用设定。
内核启动参数
主要是 nohz=off transparent_hugepage=never numa=off
内核sysctl参数
## NAT,GATEWAY:1
## net.ipv4.ip_forward = 0
## net.ipv4.ip_forward = 1
## NAT,GATEWAY:0
## net.ipv4.tcp_tw_recycle = 0
## net.ipv4.tcp_tw_recycle = 1
fs.aio-max-nr = 16777216
fs.file-max = 16777216
fs.nr_open = 16777216
kernel.core_pipe_limit = 0
kernel.core_uses_pid = 1
kernel.exec-shield = 1
kernel.randomize_va_space = 1
kernel.msgmax = 65536
kernel.msgmnb = 65536
kernel.sem = 250 32000 100 128
kernel.shmall = 4294967296
kernel.shmmax = 68719476736
kernel.sysrq = 0
kernel.pid_max = 4194303
net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.core.netdev_max_backlog = 524288
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.somaxconn=65535
net.core.wmem_default = 8388608
net.core.wmem_max = 16777216
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_notify = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_max_tw_buckets = 16777216
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_sack = 1
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_wmem = 4096 65536 4194304
net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max=25000000
net.netfilter.nf_conntrack_generic_timeout = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
vm.overcommit_memory=1
vm.swappiness = 0
###vm.min_free_kbytes=65536
net.ipv4.tcp_fastopen = 3
net.ipv4.ip_local_port_range = 10000 65535
net.ipv4.ip_local_reserved_ports =10050,11215,18000-18099,27017,60000-60099
kernel.printk_ratelimit = 30
kernel.printk_ratelimit_burst = 200
vm.max_map_count=262144
# recommended for hosts with jumbo frames enabled
#net.ipv4.tcp_mtu_probing=1
fs.inotify.max_user_watches = 30000000
#bbr
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
内核版本
内核的版本对性能和功能有显著的影响,4.9 版本加入了 BBR 功能,对性能有显著的提升。
** 升级内核版本风险较高,操作需要慎重。**
CentOS 7 内核版本为 3.10,可以使用 centos-release-xen 仓库,安装 4.9 的内核。
Ubuntu 16.04.3 HWE 内核版本的为 4.13。 如果你的内核还是默认的4.4.0,可以安装 linux-image-generic-hwe-16.04 升级到 4.13 版本。
Ubuntu 18.04 使用 4.15 版本的内核。
内核 4.9 和 4.14 为 LTS 版本,维护期一般至少为 2至 3年。
Ubuntu LTS 支持时间一般为5年,大版本之间可以平滑升级。
附升级内核版本的操作
Ubuntu :
apt-get update
apt-get dist-upgrade -y
# 安装制定版本的内核
apt-get install linux-image-4.13.0-32-generic
# 自动选择最新稳定的内核
apt-get install -y linux-image-generic-hwe
CentOS 7 方法一 :
yum install -y centos-release-xen && yum install -y kernel
CentOS 7 方法二:
安装 ELRepo,可以升级 kernel 版本,滚动升级最新的版本,后续如果内核安全补丁升级,使用稳定的版本存在安全隐患。
使用新内核
test -f /usr/sbin/update-grub && sudo update-grub
test -f /usr/sbin/grub2-mkconfig && sudo grub2-mkconfig -o /boot/grub2/grub.cfg