Nginx 在 DSP 广告系统中的优化
Contents
环境:
Distributor ID: Ubuntu
Description: Ubuntu 16.04.2 LTS
Release: 16.04
Codename: xenial
nginx version: openresty/1.11.2.5
8核心 Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz
16GB 物理内存
limit
$ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 64045
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 64045
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
nginx.conf
worker_processes auto;
worker_cpu_affinity auto;
worker_priority -20;
worker_rlimit_nofile 65535;
events {
use epoll; # 通常不需要设置, 默认情况下, Nginx 会自动选择最高效的方式的. http://nginx.org/en/docs/events.html
worker_connections 4096; # 经测试太大和太小最不好, 这个4096的值是比较适合的
multi_accept off; # 建议为默认值 off, 除非你测试时确认为 on 时有性能提升
accept_mutex off; # 当使用 epoll 或 listen reuseport 时, 要关掉这个, 当然, 默认情况下也是关闭的(注意, nginx 1.11.3之前默认是开启). http://nginx.org/en/docs/ngx_core_module.html#events
}
http {
keepalive_timeout 65;
gzip on;
upstream bid_server {
# 竞价的 server
server 内网IP:端口
# 这时根据你的 bid 服务连接数大小和nginx的情况来决定
keepalive 512;
}
server {
listen 888 deferred backlog=65535 reuseport;
server_name localhost 你的服务器网址或IP;
# 不返回 server 标识, 减少响应数据
server_tokens off;
# 完全禁止返回 Server. 上面的只是不显示版本
more_clear_headers Server;
# 禁止返回 Date
more_clear_headers Date;
keepalive_requests 10000;
keepalive_timeout 30;
location / {
# 配合 upstream 的 keepalive . 参考 https://www.nginx.com/blog/performance-tuning-tips-tricks/
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://bid_server;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 512k;
proxy_buffer_size 256k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 512k;
proxy_temp_file_write_size 512k;
}
}
}
Server 下面的参数
keepalive_requests
: 表示每个 keepalive TCP 连接, 最大可处理多少个请求. 这个在高 QPS 下要调高它
OS 层参数
sudo sysctl -a | grep "net.core\|net.ipv4.tcp" | grep "mem"
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
sudo sysctl -w net.ipv4.tcp_rmem='4096 87380 16777216'
sudo sysctl -w net.ipv4.tcp_wmem='4096 65536 16777216'
sudo sysctl -w net.core.netdev_max_backlog=300000
# 网卡队列
sudo ifconfig eth0 txqueuelen 2000
sudo ifconfig eth1 txqueuelen 2000
# 为了配合 listen 的 backlog=65535 参数
sudo sysctl -w net.core.somaxconn=65535
# 降低 TIME_WAIT 数量过多
sudo sysctl -w net.ipv4.tcp_fin_timeout=15
# 禁止自动 cork
sudo sysctl -w net.ipv4.tcp_autocorking=0
# 持久写入文件
# sudo sysctl -p
列出
sudo sysctl -a | grep tcp
关于 backlog 的参数, 可以参考 Socket参数资料收集与整理
检测是否有重传等问题
这时, 可以使用 tcpdump 输出文件, 然后利用 wireshark 分析.
一般这样子话, 可以在 nginx 的 upstream 里, keepalive 要保持好相应的大小.
client -> nginx -> upstream -> tomcat
每种情况都看看, 是否有网络传输问题.
或者
netstat -s
nstat -a
upstream 的 keepalive 问题
因为默认情况下, Nginx -> 后端的 upstream 服务器是使用 http 1.0
的. 官方文档 . 所以, 为了开启 keepalive , 可以修改该参数.
proxy_http_version 1.0
-> proxy_http_version 1.1
注意, 还要同时设置 proxy_set_header Connection "";
注意, upstream 指令下的
keepalive N;
中的 N, 表示的是每个 Nginx Worker 最大空闲的 keepalive 数量
.
通过 tcpdump 可以看到. 如果不设置的话, 默认 nginx 与 upstream 后端的HTTP 通信的请求为
HTTP/1.0
Connection: close
对 Nginx 影响比较大的参数
- upstream 中的 keepalive 以及设置
proxy_http_version 1.1;proxy_set_header Connection "";
worker_cpu_affinity auto;
worker_connections
应用程序
最好设置 CPU 亲和性
taskset -cp CPUID(从0开始) 进程 ID
查看亲和性
taskset -cp 进程 ID
减少带宽
- 减少返回的 body 字节数
- 压缩
- JSON 的 null 字段去掉
- 不必要的字节
- 使用不同的算法来压缩值. 比如 long -> 36 进制
- 减少 nignx 不必要的 Header
- 204 可以只返回
HTTP/1.1 204 No Content\r\n
- Date 去掉
- Server 去掉
Connection
去掉(http1.1
)
- 204 可以只返回
Connection 去掉要修改源码重新编译。。
541,542c541,542
< b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
< sizeof("Connection: keep-alive" CRLF) - 1);
---
> //b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
> // sizeof("Connection: keep-alive" CRLF) - 1);
参考 http-应用估算带宽
资料收集
参考<码出高效>
TIME_WAIT
: (主动关闭)无法真正释放句柄资源. 可通过sudo sysctl -w net.ipv4.tcp_fin_timeout=15
来减小超时时间. 默认是 60 . (单位是秒).CLOSE_WAIT
: (被动关闭)过多的话, 很可能是程序自身的问题, 比如程序自己忘记关闭连接.