1. ulimit优化
ulimit约束了系统最大打开的文件数量,可通过以下方式修改:
系统打开文件限制参数nofile以及系统打开进程数的限制参数nproc,建议两者都设置为65535。(使用ulimit -a验证)
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
echo "* soft nproc 65535" >> /etc/security/limits.conf
echo "* hard nproc 65535" >> /etc/security/limits.conf
2. 内核参数优化
将以下内核参数加入/etc/sysctl.conf文件中,执行sysctl -p使之生效
配置优化
1. 配置文件结构
1)全局配置
2)事件驱动模型配置
events {
...........
...........
}
3)http服务相关配置
http {
http服务全局配置
server { //虚拟主机
location { //匹配客户端访问请求,根据不同的请求做不同的响应
}
}
}
2. 全局配置
1)启动工作进程的数量,worker_processes 1;
(CPU密集型:如SSl及压缩应用,worker数量建议与CPU数量一致)
(IO密集型:如响应大量给客户,worker进程个数为CPU数量的两倍)
2)指定错误日志存放位置及日志级别 error_log logs/error.log warn;
3)指定pid文件记录nginx的主进程号 pid logs/nginx.pid;
4)指定此进程打开的最大文件描述符的值 worker_rlimit_nofile 65535;
5)每个工作进程的核心文件的最大大小 worker_rlimit_core
6)将worker与CPU绑定,worker_proceses 4;
worker_cpu_affinity 0001 0010 0100 1000。
(该示例表示分别给每个worker进程绑定一个CPU)
3. 事件驱动模型配置
1)指定epoll事件模型 use epoll;
2)每个工作进程能接受最大的客户端的连接数,提高并发连接 worker_connections 10240。
4. http服务相关配置
1)include mime.types; #文件扩展名与文件类型映射表;
2)default_type application/octet-stream; #默认文件类型,默认为text/plain;
3)定义访问日志格式。
log_format main '$remote_addr $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
"$http_user_agent" "$http_x_forwarded_for"
"$http_cookie" "$request_time" "$upstream_response_time"
"$upstream_addr" "$upstream_status"';
$remote_addr #客户端IP地址
$remote_user #客户端用户
$time_local #访问时间
$request #访问请求(请求方法 文件名称 HTTP协议版本)
$status #状态码
$body_bytes_sent #响应数据大小
$http_referer #超链接地址
$http_user_agent #浏览器类型
$http_x_forwarded_for #客户真实IP
$http_cookie #获取cookie信息
$upstream_addr #后台upstream的地址,即真正提供服务的主机地址
$upstream_response_time #请求过程中,upstream响应时间
$request_time #整个请求的总时间
其他变量:
$host #存放请求报文中的主机部分 例:https://list.jd.com/list.html?cat=4938,11760,14408(值为标红部分)
$request_uri #存放请求的URI地址,并且带有请求指令 例:https://list.jd.com/list.html?cat=4938,11760,14408(值为标红部分)
$scheme #存放客户端请求使用的协议,如http,https 例:https://list.jd.com/list.html?cat=4938,11760,14408(值为标红部分)
$document_uri #存放请求报文中的当前URI,并且不包括请求指令 例:https://list.jd.com/list.html?cat=4938,11760,14408(值为标红部分)
$server_addr #存放服务器地址
$remote_addr #存放客户端地址
$server_name #存放了客户端请求到达的服务器的名称
$request_filename #存放当前请求的资源文件的路径名
$args #存放URL中的请求指令 例:https://list.jd.com/list.html?cat=4938,11760,14408(值为标红部分)
4)访问日志的存放位置
access_log logs/access.log main;
5)客户端上传文件大小限制
client_max_body_size 100m;
6)指定来自客户端请求头的headerbuffer大小
client_header_buffer_size 32K;
#大多数请求1K的缓冲区即可,如果cookie较大可增加缓冲区大小。
7)指定客户端请求中较大的消息头的缓存最大数量和大小
large_client_header_ buffers 4 32K;
# 4为个数,32K为大小,最大缓存为量为4个32K。
8)开启sendfile机制
sendfile on;
#该机制由内核直接将内容复制到nginx进程对应的内容,节省文件拷贝的时间。
9)#tcp_nopush on;
#仅在使用sendfile时开启,响应头和正文的开始部分一同发送。
10)#tcp_nodelay on;
#只在长连接中启用,用于减缓网络堵塞,但及建议不要与tcp_nopush同时使用。
11)每条长连接的超时时间
keepalive_timeout 65;
12)限制长连接所能发送的最大请求数
keepalive_requests 100;
13)限制请求体的大小
client_max_body_size 100m;
#若超过所设定的大小,返回413错误。
14)gzip压缩模块
gzip on; #开启压缩模块
gzip_min_length 4K; #允许压缩的页面最小字节数,默认值为0(建议设置大于1K,小于1K可能越压越大)
gzip_buffers 4 16K; #用于处理请求压缩的缓冲区数量和大小,申请4个16K的内存作为数据流缓冲
gzip_http_version 1.1; #用于设置识别http协议版本,默认为1.1
gzip_comp_level 2; #用来指定压缩比,1压缩比最小处理速度最快,9压缩比最大,传输速度快,处理慢,同时较耗费CPU资源
15)对请求进行限速
limit_req_zone zone=one:10m rate=5r/s; #表示一个内存区域大小为10m,并且设定了名称为one,且请求的速率是1秒5个请求。
16)定义缓存空间
proxy_cache_path /nginx/cache/first levels-2:1:2 keys_zone=first:20m max_size=1G;
levels-2:1:2 #定义缓存目录子目录的级别,以及每个子目录的名称字符个数;最多只能有三级子目录;
3级子目录,第1级目录字符个数为1,第2级目录字符个数为2,第3级目录字符个数为2,字符个数最多只能有2个;
/nginx/cache/first #在磁盘产生的目录存储缓存数据;
max_size=1G #指定/nginx/cache/first中的1G空间用于存储缓存数据。
5. server虚拟主机
1)监听端口 listen 80;
2)设置虚拟主机名称 server_name localhost。
6. location块
1)自动索引模块HttpAutoindex
autoindex on; #当网页目录中没有index.html文件,该目录以下载网站的方式展现;
2)限制模块HttpLimit zone
该模块可以针对条件,进行会话的并发连接数控制。(例如:限制每个IP的并发连接数。)
http {
limit_zone one $binary_remote_addr 10m;
server {
location /download/ {
limit_conn one 1;
}
限制的区域名是one,容量是10M,以变量 $binary_remote_addr 作为会话的判断基准(即一个地址一个会话)。
$remote_addr 的长度为 7 至 15 bytes,会话信息的长度为 32 或 64 bytes;
而 $binary_remote_addr 的长度为 4 bytes,会话信息的长度为 32 bytes。
当区的大小为 1M 的时候,大约可以记录 32000 个会话信息(一个会话占用 32 bytes)。
3)HttpLimitReqest模块
该模块可限制给定会话的请求数。
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
location /search/ {
limit_req zone=one burst=5; #允许用户平均每秒不超过1个请求,突发不超过5个查询
}
}
}
4)StubStatus模块
该模块能够获取Nginx自上次启动以来的工作状态,此模块非核心模块,需要在编译的时候手动添加编译参数--with-http_stub_status_module。
location /status {
stub_status on; #开启该模块
access_log off;
allow ***.***.230.1; #允许访问的ip地址
deny all; #拒绝所有ip地址访问
}
5)proxy模块
proxy_pass http://itower;
proxy_redirect default; #默认配置为default,建议默认即可;如果设置off,则将禁止所有的proxy_redirect指令;
proxy_buffering off;
proxy_connect_timeout 600; #向后端服务器等待建立连接的超时时间; 单位s;
proxy_set_header Host $host:$server_port;
proxy_send_timeout 600; #向后端服务器发送write请求时等待的超时时间; 单位s;
proxy_read_timeout 600; #向后端服务器发送read请求时等待的超时时间; 单位s;
proxy_buffer_size 8k; #用于配置接收一次后端服务器的响应数据的proxy buffer的个数和每个buffer的大小;
proxy_cache first; #开启缓存,结合http块中的proxy_cache_path使用;
proxy_cache_vaild 200 1m; #表示为状态码为200的数据缓存1分钟,结合http块中的proxy_cache_path使用。
-----------------------静态压缩和动态压缩结合使用
# 启动静态压缩
gzip_static on;
gzip_proxied expired no-cache no-store private auth;
# 启用压缩,html/js/css压缩之后,传输更快,节约带宽
gzip on;
# 限制最小压缩,小于1个字节的文件不会压缩
gzip_min_length 15k;
# gzip申请内存的大小,其作用是按块大小的倍数申请内存空间
gzip_buffers 4 16k;
# 定义压缩级别 (压缩比,文件越大,压缩越多,但是cpu使用会越多)
gzip_comp_level 5;
# 配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_disable "MSIE [1-6]\.";
# 是否添加“Vary: Accept-Encoding”响应头
gzip_vary on;
# 定义压缩文件的类型
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jepg image/gif image/png application/json;
注意事项:
gzip_static配置优先级高于gzip
开启nginx_static后,对于任何文件都会先查找是否有对应的gz文件
gzip_types设置对gzip_static无效
# 核心参数(其他参数大部分情况下用不到)
# user USERNAME [GROUP]
# 解释:指定运行nginx的worker子进程的属主和属组,其中属组可以不指定
user nginx;
# worker_processes NUMBER | auto
# 解释:指定nginx启动的worker子进程数量
# 【*auto:自动设置为物理CPU核心数】
worker_processes auto;
# pid DIR
# 解释:指定运行nginx的master主进程的pid文件存放路径
pid /opt/nginx/logs/nginx.pid;
# worker_rlimit_nofile NUMBER
# 解释:指定worker子进程可以打开的最大文件句柄数
# 【系统最大打开65535,每个子进程打开数乘子进程数,实际也不会超过65535】
# 这个值需要调大,最好与 ulimit -n 的值保持一致。
worker_rlimit_nofile 65535;
# worker_rlimit_core SIZE
# 指定worker子进程异常终止后的core文件,用于记录分析问题
worker_rlimit_core 50M;
working_directory /opt/nginx/tmp;#【必须对子进程用户赋写权限】
# 解释:将每个worker子进程与CPU物理核心绑定
# 【master负责调度,worker负责处理请求】
# 【假设CPU有4个核心,某一时刻worker1获取到了CPU1的工作调度时间片,时间片过后worker1从CPU1上面撤下来,CPU1去处理其他事件,下一时刻可能是CPU2、CPU3的时间片调度到了worker1上面,那么worker1就会在其他CPU上面工作,进程与CPU的调度切换是有损耗的,worker1如果绑定了CPU1,worker1将永远等待CPU1的调度,充分利用CPU缓存】
# 【【主要作用:将每个worker子进程与特定CPU物理核心绑定,优势在于:避免同一个worker子进程在不同的CPU核心上切换,缓存失效,降低性能;其并不能真正避免进程切换(进程切换是CPU工作特性)】】
# -- worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;# 8核心,8个worker
# -- worker_cpu_affinity 01 10;# 2核心,2个worker
worker_cpu_affinity 0001 0010 0100 1000;# 4核心,4个worker
# 解释:指定worker子进程的nice值,以调整运行nginx的优先级,通常设定为“负值”,以优先调用nginx
# 【值越小越优先;nice设定范围为-20到+19】
worker_priority -20;
# 指定worker子进程优雅退出时的超时时间,不管5秒内是否处理完,都强制退出
worker_shutdown_timeout 5s;
# worker子进程内部使用的计时器精度,调整时间间隔越大,系统调用越少,有利于性能提升;反之,系统调用越多,性能下降
# 比如某些计时的操作,worker需要去获取内核时间,频繁跟内核打交道会降低性能
timer_resolution 100ms;
# daemon on | off
# 设定nginx的运行方式,前台还是后台,前台用户调试,后台用于生产
daemon on;
events {
# Nginx使用何种事件驱动模型
# 【高并发场景下,I/O多路复用使用epoll模型,提高效率】
use epoll;
# 单个worker子进程能够处理的最大并发连接数,多核情况最大其实达不到65535,
worker_connections 65535;
# 是否打开负载均衡互斥锁,默认off(当master接收到请求时,会给每个worker发送消息去唤醒,状态为on时,则会有一个负载均衡锁,master会轮流发给每一个)
accept_mutex off;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
# 开启高效的 零拷贝技术 进行文件传输;
# 这样只需要 2 次上下文切换,和 2 次数据拷贝,在内核态即可完成,由DMA进行文件搬运,不需要CPU参与
sendfile on;
# 必须在sendfile开启时才有效,防止网路阻塞,减少网络报文段的数量(将响应头和正文的开始部分一起发送,而不一个接一个的发送)
tcp_nopush on;
# 客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接
keepalive_timeout 60;
# 防止网络阻塞
tcp_nodelay on;
# 客户端请求头部的缓冲区大小,根据系统分页大小来设置,命令 getconf PAGESIZE 取得分页大小
client_header_buffer_size 4k;
# 为打开文件指定缓存,默认是没有启用的,max 指缓存数量,建议和打开文件数一致,inactive 指经过多长时间文件没被请求后删除缓存
open_file_cache max=65536 inactive=30s;
# 多长时间检查一次缓存的有效信息
open_file_cache_valid 30s;
# open_file_cache 指令中的 inactive 参数时间内文件的最少使用次数
# 如果超过这个数字,文件描述符一直是在缓存中打开的,如果一个文件在 inactive 时间内一次没被使用,它将被移除
open_file_cache_min_uses 1;
# 设置请求头的超时时间,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误
client_header_timeout 15;
# 设置请求体的超时时间,超过这个时间没有发送任何数据,和上面一样的错误提示
client_body_timeout 15;
# 告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间
reset_timedout_connection on;
# 应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接
send_timeout 15;
# 上传文件大小限制
client_max_body_size 10m;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /video/ {
sendfile on;
# 当文件大小超过8M时,启用AIP与directio
aio on;
directio 8m;
}
# HTTPS server
server {
# 开启http2
# http2 在底层传输做了很大的改动和优化:
# 1,每个服务器只用一个连接,节省多次建立连接的时间,在TLS上效果尤为明显
# 2,加速 TLS 交付,HTTP/2 只耗时一次 TLS 握手,通过一个连接上的多路利用实现最佳性能
# 3,更安全,通过减少 TLS 的性能损失,让更多应用使用 TLS,从而让用户信息更安全
listen 443 ssl http2;
server_name localhost;
## 证书部分
#ECC证书
# 256 位 ECC Key 在安全性上等同于 3072 位 RSA Key,运算速度更快,同等安全条件下,ECC 算法所需的 Key 更短,所以 ECC 证书文件体积比 RSA 证书要小一些。
ssl_certificate ecc.crt;
#ECC密钥
ssl_certificate_key ecc.key; #ECC密钥
ssl_certificate cert.pem; # RSA证书
ssl_certificate_key cert.key; # RSA密钥
# TLS 握手优化
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
keepalive_timeout 75s;
keepalive_requests 100;
# 支持TLSv1.3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;
# 开启 1.3 o-RTT
ssl_early_data on;
ssl_prefer_server_ciphers on;
# gzip
gzip on;
# 压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源
gzip_comp_level 6;
# 设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0
gzip_min_length 1k;
# 用来指定压缩的类型,‘text/html’类型总是会被压缩。默认值: gzip_types text/html (默认不对js/css文件进行压缩)
# 缩类型,匹配MIME型进行压缩,不能用通配符 text/* text/html默认已经压缩 (无论是否指定)
# 设置哪压缩种文本文件可参考 conf/mime.types
gzip_types text/plain text/css text/xml text/javascript text/x-component application/json application/javascript application/x-javascript application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;
# brotli:Google 推出的无损压缩算法,有以下优势:
# 1,针对常见的 Web 资源内容,Brotli 的性能要比 Gzip 好 17-25%;
# 2,Brotli 压缩级别为 1 时,压缩速度是最快的,而且此时压缩率比 gzip 压缩等级为 9(最高)时还要高;
brotli on;
brotli_comp_level 6;
brotli_min_length 1k;
brotli_types text/plain text/css text/xml text/javascript text/x-component application/json application/javascript application/x-javascript application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;
location / {
root html;
index index.html index.htm;
}
}
}
支持 TLS1.3 和 brotli ,都需要编译时引入相应模块
cd /opt/$nginxVersion/
./configure \
--prefix=/usr/local/nginx \ ## 编译后安装的目录位置
--with-openssl=/opt/$OpenSSLVersion \ ## 指定单独编译入 OpenSSL 的源码位置
--with-openssl-opt=enable-tls1_3 \ ## 开启 TLS 1.3 支持
--with-http_v2_module \ ## 开启 HTTP/2
--with-http_ssl_module \ ## 开启 HTTPS 支持
--with-http_gzip_static_module \ ## 开启 GZip 压缩
--add-module=/opt/ngx_brotli ## 编译入 ngx_BroTli 扩展
make && make install ## 编译并安装
Linux 内核参数优化
- 修改文件:
/etc/sysctl.conf
- 执行
/sbin/sysctl -p
,使配置生效
# 表示进程(比如一个worker进程)可以同时打开的最大句柄数,这个参数直接限制最大并发连接数,需根据实际情况配置
fs.file-max = 999999
# 控制系统调试内核的功能,不同的值对应不同的功能
# 0 完全禁用 sysrq 组合键
# 1 启用 sysrq 组合键的全部功能
# 2 启用控制台日志级别控制
# 4 启用键盘控制(SAK、unraw)
# 8 启用进程的调试信息输出等
# 16 启用同步命令
# 32 启用重新挂载为只读
# 64 启用进程信号(终止、杀死、溢出杀死)
# 128 允许重启/关机
# 256 控制实时任务的优先级控制(nicing)
kernel.sysrq = 0
# core_uses_pid 可以控制 core 文件的文件名中是否添加 pid 作为扩展名
# 设置为1,表示添加 pid 作为扩展名,生成的 core 文件格式为 core.xxx;设置为0(默认),表示生成的 core 文件统一命名为 core
kernel.core_uses_pid = 1
# 规定了一个消息队列的最大值,即一个消息队列的容量,msgmnb 控制可以使用的共享内存的总页数
# Linux共享内存页大小为4KB,共享内存段的大小都是共享内存页大小的整数倍
# 一个共享内存段的最大大小是 16G,那么需要共享内存页数是16GB / 4KB = 16777216KB / 4KB = 4194304(页)
kernel.msgmnb = 65536
# 进程间的消息传递是在内核的内存中进行的。msgmax 指定了消息队列中消息的最大值(65536B=64KB)
kernel.msgmax = 65536
# 内核所允许的最大共享内存段的大小(bytes)
kernel.shmmax = 68719476736
# 表示在任何给定时刻,系统上可以使用的共享内存的总量(bytes)
kernel.shmall = 4294967296
# 表示内核套接字发送缓存区默认的大小
net.core.wmem_default = 8388608
# 表示内核套接字接受缓存区默认的大小
net.core.rmem_default = 8388608
# 表示内核套接字接受缓存区的最大大小
net.core.rmem_max = 16777216
# 表示内核套接字发送缓存区的最大大小
net.core.wmem_max = 16777216
# 接收自网卡,但未被内核协议栈处理的报文队列长度
net.core.netdev_max_backlog = 262144
# web 应用中 listen 函数的 backlog 默认会给我们内核参数的
# 对于一个TCP连接,Server与Client需要通过三次握手来建立网络连接
# 当三次握手成功后,我们可以看到端口的状态由LISTEN转变为ESTABLISHED,接着这条链路上就可以开始传送数据了
# 每一个处于监听(Listen)状态的端口,都有自己的监听队列.监听队列的长度与如somaxconn参数和使用该端口的程序中listen()函数有关
# somaxconn定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128
# 对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多
# 大的侦听队列对防止拒绝服务 DoS 攻击也会有所帮助
net.core.somaxconn = 40960
# 不充当路由器
net.ipv4.ip_forward = 0
# 控制系统是否开启对数据包源地址的校验
# 0 不开启源地址校验
# 1 开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径,则直接丢弃该数据包
# 2 开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包
net.ipv4.conf.default.rp_filter = 1
# 使用sysrq组合键是了解系统目前运行情况,为安全起见设为0关闭
net.ipv4.conf.default.accept_source_route = 0
# 启用有选择的应答(1表示启用)
# 通过有选择地应答乱序接收到的报文来提高性能,让发送者只发送丢失的报文段,(对于广域网通信来说)这个选项应该启用,但是会增加对CPU的占用
net.ipv4.tcp_sack = 1
# tcp窗口大于64K时,必须开启此值
net.ipv4.tcp_window_scaling = 1
# TCP读缓存的最小值、默认值、最大值,单位字节
net.ipv4.tcp_rmem = 10240 87380 12582912
# TCP读缓存的最小值、默认值、最大值,单位字节
net.ipv4.tcp_wmem = 10240 87380 12582912
# TCP的内存大小,单位是页,1页等于4096字节,单位为页的数量
net.ipv4.tcp_mem = 94500000 915000000 927000000
# 系统中最多有多少个 TCP 套接字不被关联到任何一个用户文件句柄上
# 这个限制仅仅是为了防止简单的 DoS 攻击,如果增加了内存之后,更应该增加这个值
net.ipv4.tcp_max_orphans = 3276800
# SYN队列的长度,默认为1024,加大队列长度为262144,可以容纳更多等待连接的网络连接数
net.ipv4.tcp_max_syn_backlog = 262144
# 用于设置时间戳,可以避免序列号的卷绕
# 一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。设置为 0 表示将其关掉
net.ipv4.tcp_timestamps = 0
# 内核放弃连接之前发送 SYN+ACK 包的数量
# 被动建立连接时,发送SYN/ACK的重试次数
net.ipv4.tcp_synack_retries = 1
# 主动建立连接时,发送SYN的重试次数
net.ipv4.tcp_syn_retries = 1
# 开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1
# 开启重用。作为客户端时,新连接可以使用仍然处于 TIME-WAIT 状态的端口,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1
# TIME_WAIT 状态连接的最大数量,超出后直接关闭连接
net.ipv4.tcp_max_tw_buckets = 6000
# fin_wait1状态,发送fin报文的重试次数,0相当于8
net.ipv4.tcp_orphan_retries = 0
# fin_wait2状态,默认的 TIMEOUT 时间
net.ipv4.tcp_fin_timeout = 15
# 当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时
net.ipv4.tcp_keepalive_time = 1200
# 探测包发送间隔
net.ipv4.tcp_keepalive_intvl = 75
# 探测包重试次数
net.ipv4.tcp_keepalive_probes = 6
#开启SYN Cookies 当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
net.ipv4.tcp_syncookies = 1
# 建立连接时的本地端口可用范围
net.ipv4.ip_local_port_range = 1024 65000
HTTPS优化
1.开启http2
HTTP/2标准是从Google的SPDY上进行改进的,比起HTTP/1.1提升了不少性能,尤其是需要并行多个请求的时候可以显著减少延迟。在现在的网络上,一个网页平均需要请求几十次,而在 HTTP 1.1 时代浏览器能做的就是多开几个TCP连接(通常是 6 个)进行并行HTTP请求,而 HTTP 2 中可以在一个TCP连接中进行多个HTTP请求。HTTP 2 原生支持多个并行请求,因此大大减少了顺序执行的请求的往返程
HTTP是基于TCP上的协议,每一次HTTP请求都需要先建立一次TCP。到了HTTP/2,一个TCP可以发送多个HTTP请求
listen 443 ssl;
# 改为
listen 443 ssl http2;
如果你担心你的用户用的是旧的客户端,比如 Python 的 requests,暂时还不支持 HTTP 2 的话,那么其实不用担心。如果用户的客户端不支持 HTTP 2,那么连接会自动降级为 HTTP 1.1,保持了后向兼容。因此,所有使用旧 Client 的用户,仍然不受影响,而新的客户端则可以享受 HTTP/2 的新特性
如何确认:
在 Chrome 中打开开发者工具,点开 Protocol 之后在所有的请求中都可以看到请求用的协议了。如果 protocol 这列的值是 h2 的话,那么用的就是 HTTP 2 了
在Nginx中,对于http1.0与http1.1是支持长连接的
http请求是基于TCP协议之上的,那么当客户端在发起请求前,需要先与服务端建立TCP连接,而每一次的TCP连接是需要三次握手来确定的,如果客户端与服务端之间网络差一点,这三次交互消费的时间会比较多,而且三次交互也会带来网络流量。当然,当连接断开后,也会有四次的交互。在一个连接上面执行多个请求,就能节省很多时间和流量
1. 开启长连接
# 开启长连接并设置连接超时时间
keepalive_timeout 120s;
#设置一个长连接最多可以服务多少个请求,超过自动关闭
keepalive_requests 100;
2. 启用SSL Session缓存
启用 SSL Session 缓存可以大大减少 TLS 的反复验证,减少 TLS 握手的 roundtrip。虽然 session 缓存会占用一定内存,但是用 1M 的内存就可以缓存 4000 个连接,可以说是非常非常划算的。同时,对于绝大多数网站和服务,要达到 4000 个同时连接本身就需要非常非常大的用户基数,因此可以放心开启。
#设置ssl session缓存(10m是指缓存大小10兆)
ssl_session_cache shared:SSL:50m;
#设置长连接缓存过期时间
ssl_session_timeout 4h;
3. 调整ssl_buffer_size
ssl_buffer_size 控制在发送数据时的 buffer 大小,默认设置是 16k。这个值越小,则延迟越小,而添加的报头之类会使 overhead 会变大,反之则延迟越大,overhead 越小。因此如果你的服务是 REST API 或者网站的话,将这个值调小可以减小延迟和 TTFB,但如果你的服务器是用来传输大文件的,那么可以维持 16k。如果是网站或者 REST API,建议值为 4k,但是这个值的最佳取值显然会因为数据的不同而不一样,因此请尝试 2 - 16k 间不同的值。
ssl_buffer_size 6K;
静态文件加载优化
Nginx优化静态文件加载主要针对图片、js、css及html文件,优化方案主要分为 HTTP缓存 和 文件压缩。
HTTP缓存是指客户端通过HTTP返回的头部信息判断是否缓存。缓存方式为客户端本地存储。
文件压缩是指服务器将静态文件通过gzip打包压缩后再返回给客户端,客户端再通过HTTP返回的头部信息进行解压,之后再进行解析渲染
HTTP缓存:主要通过在http返回的头部添加 Cache-Control 和 Expires 来实现
Cache-Control:控制是否缓存
Expires:控制缓存时间
静态文件中图片一般不做gzip压缩,大部分图片都是经过压缩,gzip再进行压缩效果不大。对于js、css、html及字体文件而言,gzip压缩效果非常明显
expires off | time;
配置范围:http、server、location、if in location
例如:
1. 开启缓存,过期时间24小时:expires 24h;
2. 关闭缓存(默认是关闭状态):expires off;
对于js、css及html除了http缓存优化外还可以使用压缩方式返回。
例如:一个index.css文件大小为100KB,经过gzip压缩后可能就只有十几KB。
# 开启gzip压缩
gzip on | off;
#设置压缩级别(默认为1)
gzip_comp_level level;
上述配置范围:http,server,location
部分浏览器可能不支持gzip压缩问题,大家可以开启gunzip 配置如下
http_gunzip_module on | offf;
现在我们已经知道优化配置选项,在实际工作中我们可能需要针对不同域名进行优化,区别图片和其他静态文件进行优化。这些究竟怎么去实现呢?下面我们就来看看完整的配置:
server {
listen 80;
server_name test.cn;
root /data/www/test;
location ~ .*\.(html|js|css|woff){
access_log off;
expires 168h;
gzip on;
gzip_comp_level 5;
gzip_types text/plain application/javascript text/css font/woff;
}
location ~ .*\.(png|jpg|jpeg|gif){
access_log off;
valid_referers *.test.cn servicewechat.com none;
if ($invalid_referer) {
return 403;
}
expires 168h;
}
location / {
index index.html index.htm;
}
location ~ /api {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:9502;
}
}
在上述nginx配置中,我们会发现所有静态文件的访问关闭了访问日志【access_log off;】。
图片简单的做了防盗链功能,其中servicewechat.com是微信小程序的域名,这样小程序中也可以访问图片资源。
js、css、html及字体文件做了压缩功能,减少服务器带宽压力,加快用户访问速度。
上述配置中,nginx转发php-fpm的配置中忽略了很多配置信息,这里建议大家在location ~ /api 中加载 fastcgi_params文件。fastcgi_params是Nginx官方提供的文件,大家可以放心使用。