本文介绍nignx相关内容

安装,以centos7为例

yum安装

  • 添加yum源
cat > /etc/yum.repo.d/nginx.repo << EOF      
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
EOF  
  • 刷新yum缓存
yum makecache fast
  • 安装nginx
yum install nginx -y

编译安装

  • 安装依赖
yum install gcc gcc-c++ pcre pcre-devel openssl openssl-devel zlib zlib-devel make automake -y
  • 创建用户
useradd -s /sbin/nologin nginx 
  • 下载安装包
wget http://nginx.org/download/nginx-1.16.0.tar.gz
tar -zxvf nginx-1.16.0.tar.gz
cd nginx-1.16.0
  • 编译配置
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_v2_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module 
  • 开始编译
make && make install
  • 创建服务配置文件
cat > /usr/lib/systemd/system/nginx.service << EOF
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload= /usr/local/nginx/sbin/nginx -s reload
ExecStop= /usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
  • 添加执行权限
chmod +x /usr/lib/systemd/system/nginx.service
  • 启动并设置开机启动
systemctl enable --now nginx.service

nginx调优

  • 系统连接数的优化
cat >> /etc/security/limits.conf  << EOF
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF
  • 内核优化
net.ipv4.ip_nonlocal_bind = 1
#作为负载均衡服务器一定要开启(LVS、haproxy、nginx),允许某个服务监听在本机所没有的IP地址的端口上,如LVS的vip;作为负载均衡服务器不开启此参数,则服务是无法起来的。
net.ipv4.ip_forward = 1 
#开启ipv4转发功能,用于跨网段转发;负载均衡服务器一定要开启。
net.ipv4.tcp_timestamps = 0
#给报文添加时间戳,会对添加时间戳的报文做校验;作为web服务器可开启,作为负载均衡服务器一定要关闭。一个局域网内,都是用一个公网IP,如果访问一个网站的index.html资源,负载均衡服务器处理完一个请求后,又有第二个相同的IP访问相同网站的index.html,这时负载均衡服务器会把第二个报文校验完毕后,发现IP和请求的资源一致,会把报文抛弃掉,所以作为负载均衡服务器必须关闭此参数。
net.ipv4.tcp_tw_reuse = 0
#端口复用;依赖于net.ipv4.tcp_timestamps参数,如果net.ipv4.tcp_timestamps开启,则net.ipv4.tcp_tw_reuse生效,如果没开启,则此参数也不生效。
#参数设置为 1 ,表示允许将TIME_WAIT状态的socket重新用于新的TCP链接,这对于服务器来说意义重大,因为总有大量TIME_WAIT状态的链接存在;用于TCP连接。
net.ipv4.tcp_tw_recycle = 0 
#快速回收TIME_WAIT状态,用于大量TIME_OUT场景;依赖于net.ipv4.tcp_timestamps参数。
#这个参数用于设置启用timewait快速回收;开启后,用户如果正在看网页,过会儿再点,会发现断开连接,会重新TCP三次握手建立连接。
fs.file-max = 1000000
#表示单个进程最多可以打开的文件描述符的数量。
net.ipv4.tcp_keepalive_time = 600
#当keepalive启动时,TCP发送keepalive消息的频度;默认是2小时,将其设置为10分钟,可更快的清理无效链接。
net.ipv4.tcp_fin_timeout = 30
#当服务器主动关闭链接时,socket保持在FIN_WAIT_2状态的较大时间。
net.ipv4.tcp_max_tw_buckets = 5000
#表示操作系统允许TIME_WAIT套接字数量的较大值,如超过此值,TIME_WAIT套接字将立刻被清除并打印警告信息,默认为8000,过多的TIME_WAIT套接字会使Web服务器变慢。
net.ipv4.ip_local_port_range = 1024 65000
#定义UDP和TCP链接的本地端口的取值范围。
net.ipv4.tcp_rmem = 10240 87380 12582912
#定义了TCP接受socket请求缓存的内存最小值、默认值、较大值。
net.ipv4.tcp_wmem = 10240 87380 12582912
#定义TCP发送缓存的最小值、默认值、较大值。
net.core.netdev_max_backlog = 8096
#当网卡接收数据包的速度大于内核处理速度时,会有一个列队保存这些数据包。这个参数表示该列队的较大值。
net.core.rmem_default = 6291456
#表示内核套接字接受缓存区默认大小。
net.core.wmem_default = 6291456
#表示内核套接字发送缓存区默认大小。
net.core.rmem_max = 12582912
#表示内核套接字接受缓存区较大大小。
net.core.wmem_max = 12582912
#表示内核套接字发送缓存区较大大小。
注意:以上的四个参数,需要根据业务逻辑和实际的硬件成本来综合考虑。
net.ipv4.tcp_syncookies = 1
#与性能无关。用于解决TCP的SYN攻击。
net.ipv4.tcp_max_syn_backlog = 8192
#这个参数表示TCP三次握手建立阶段接受SYN请求列队的较大长度,默认1024,将其设置的大一些可使出现。
Nginx繁忙来不及accept新连接时,Linux不至于丢失客户端发起的链接请求。
net.core.somaxconn = 262114
#选项默认值是128,这个参数用于调节系统同时发起的TCP连接数,在高并发的请求中,默认的值可能会导致链接超时或者重传,因此需要结合高并发请求数来调节此值。
net.ipv4.tcp_max_orphans=262114
#选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤立链接将立即被复位并输出警告信息。这个限制指示为了防止简单的DOS攻击,不用过分依靠这个限制甚至认为的减小这个值,更多的情况是增加这个值。

nignx配置

  • 重点配置解读
user  nginx; # 系统用户为nginx
worker_processes  4; #如果服务器为4核,这里配4
worker_cpu_affinity 0001 0010 0100 1000; #如果服务器为4核,需要多核处理,则这么配
worker_rlimit_nofile 65535;

error_log  /var/log/nginx/error.log warn;

events {
    use epoll;
    worker_connections 20480; #提高并发
}
http {
    access_log  /var/log/nginx/access.log  main;
    client_max_body_size 10M; #最大上传量
    underscores_in_headers on; #header不区分大小写
    tcp_nodelay on;
    #tcp_nodelay off,会增加通信的延时,但是会提高带宽利用率。在高延时、数据量大的通信场景中应该会有不错的效果
    #tcp_nodelay on,会增加小包的数量,但是可以提高响应速度。在及时性高的通信场景中应该会有不错的效果
    include /etc/nginx/conf.d/*.conf;
 }
  • 日志配置(输出为json格式,方便elasticsearch解析)
      log_format main escape=json
    '{"@timestamp":"$time_iso8601",'
    '"host":"$hostname",'
    '"server_ip":"$server_addr",'
    '"client_ip":"$remote_addr",'
    '"xff":"$proxy_add_x_forwarded_for",'
    '"domain":"$host",'
    '"url":"$uri",'
    '"referer":"$http_referer",'
    '"args":"$args",'
    '"upstream_time":"$upstream_response_time",'
    '"response_time":"$request_time",'
    '"request_method":"$request_method",'
    '"status_code":"$status",'
    '"size_num":"$body_bytes_sent",'
    '"request_body":"$request_body",'
    '"request_length":"$request_length",'
    '"protocol":"$server_protocol",'
    '"upstreamhost":"$upstream_addr",'
    '"file_dir":"$request_filename",'
    '"http_user_agent":"$http_user_agent"'
  '}';
  • 我用的配置(不要直接复制,会起不来)
user  nginx;
worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 65535;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    use epoll;
    worker_connections 20480;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

      log_format main escape=json
    '{"@timestamp":"$time_iso8601",'
    '"host":"$hostname",'
    '"server_ip":"$server_addr",'
    '"client_ip":"$remote_addr",'
    '"xff":"$proxy_add_x_forwarded_for",'
    '"domain":"$host",'
    '"url":"$uri",'
    '"referer":"$http_referer",'
    '"args":"$args",'
    '"upstream_time":"$upstream_response_time",'
    '"response_time":"$request_time",'
    '"request_method":"$request_method",'
    '"status_code":"$status",'
    '"size_num":"$body_bytes_sent",'
    '"request_body":"$request_body",'
    '"request_length":"$request_length",'
    '"protocol":"$server_protocol",'
    '"upstreamhost":"$upstream_addr",'
    '"file_dir":"$request_filename",'
    '"http_user_agent":"$http_user_agent"'
  '}';

    access_log  /var/log/nginx/access.log  main;
    server_names_hash_bucket_size 512; 
    sendfile        on;
    server_tokens off;
    keepalive_timeout  30;
    client_header_buffer_size 4k;
    client_max_body_size 10M;
    underscores_in_headers on;
    tcp_nodelay on;
    gzip on;
    gzip_buffers 32 4K;
    gzip_comp_level 6;
    gzip_min_length 100;
    gzip_types application/javascript text/css text/xml;
    gzip_disable "MSIE [1-6]\."; 
    gzip_vary on;
    more_clear_headers 'Server';
    include /etc/nginx/conf.d/*.conf;
}

转发配置

是否带证书

  • 带证书
server {
    listen 443 ssl;
    server_name {{域名}};
    ssl_certificate      /etc/nginx/certs/{{证书名}}.pem;
    ssl_certificate_key  /etc/nginx/certs/{{证书名}}.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    location / {
      proxy_pass http://192.168.1.132:30057;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }
}
  • 不带证书
server {
    listen 80;
    location / {
      proxy_pass http://192.168.1.132:30057;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }
}

upstream方法

  • 多个后端地址
upstream {{应用别名}}{
  server 192.168.1.130:30070 max_fails=3 fail_timeout=30s weight=1;
  server 192.168.1.131:30070 max_fails=3 fail_timeout=30s weight=1;
}

server { 
  listen 30070;
  location / {
      proxy_pass http://{{应用别名}}/;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  }
}

转发规则

  • 模糊匹配域名后面的第一级aaa转发到特定地址
server {
    listen 80;
     location / {
      proxy_pass http://192.168.1.132:30064;   
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }

    location ^~ /aaa/ {  
      proxy_pass http://192.168.1.132:30070/;   
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }
}
  • 绝对匹配域名为/aaa/notify的路由转发到特定地址
server {
    listen 80;
     location / {
      proxy_pass http://192.168.1.132:30064;   
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }

    location /aaa/notify {  
      proxy_pass http://192.168.1.132:30070/aaa/notify;   
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }
}
  • 通过header中的参数值判断转发,将channel为online转发到特定地址
server {
  listen 80;
  location / {
      #参数格式为 $http_{{参数名}}
      if ($http_channel = "online") {
         proxy_pass http://192.168.1.32:20007;
      }
      proxy_pass http://192.168.1.106:16000;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }
}
  • 设置访问白名单
server {
  listen 80;

  allow 192.168.1.1;  # 对方出口地址
  deny all;  # 拒绝所有其它地址
  location / {
      proxy_pass http://192.168.1.37:20009;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }
}

高并发优化

nginx后端使用k8s集群应用提供服务,需与k8s的服务保持长连接,并增加缓冲区空间。
如果不设置长连接,每次建立连接花费的时间将会影响接口响应的速度,如果是高并发场景,连接会在释放与连接状态中不停切换,导致接口响应的效果变差。具体压测数据可以参考文章

upstream {{应用别名}}{
  server 192.168.1.36:30057 max_fails=3 fail_timeout=30s weight=1;
  server 192.168.1.30:30057 max_fails=3 fail_timeout=30s weight=1;
  server 192.168.1.31:30057 max_fails=3 fail_timeout=30s weight=1;
}

server {
    listen 30057;
    location / {
      proxy_pass http://{{应用别名}}/;
      proxy_connect_timeout 75;
      proxy_read_timeout 300;
      proxy_send_timeout 300;
      proxy_buffer_size 64k;
      proxy_buffers   4 64k;
      proxy_busy_buffers_size 128k;
      proxy_temp_file_write_size 128k;
      proxy_http_version 1.1;
      proxy_set_header Connection "Keep-Alive";
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     }

}

感谢

nginx入门之—-编译安装
nginx之系统参数优化