Nginx 配置(系列二) 性能篇
在之前的文章 本博客 Nginx 配置(系列一) 安全篇 中,我介绍了本博客的 Nginx 配置中与安全相关的项目。这篇帖子会继续介绍与站点性能相关的条目。
TCP 优化
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 60;
}
server {
listen 443 fastopen=3 reuseport;
}
sendfile
可以提高 Nginx 静态资源管理效率,它是一个系统调用,直接在内核空间完成文件发送,不需要先 read 再 write,没有上下文切换开销。
tcp_nopush
是 FreeBSD 的一个 socket 选项,对应于 Linux 的 tcp_cork,Nginx 中统一用 tcp_nopush 控制,且只有在启用了 sendfile 后才会生效。启用它后,数据包会累计到一定大小后才会发送,减小额外开销,提高网络效率。
tcp_nodelay
也是一个 socket 选项,启用后会禁用 Nagle 算法,尽快发送数据。Nginx 只会针对处于 keep-alive 状态的 TCP 连接启用 tcp_nodelay。
然后你会发现,一个要等数据包累积到一定大小才发送,另一个要尽快发送,这不是矛盾的吗?事实是,这俩是可以叠加的,最终结果是:先填满包,然后尽快发送。
keepalive_timeout
用于指定服务端每个 TCP 连接的最大保持连接时间。Nginx 默认是 75 秒,而有的浏览器最多只保持 60 秒,所以我设置为 60。
fastopen=3
用于指定开启 Tcp Fast Open。设置这项的值为 3,表示只允许 3 个未经三次握手的 TCP 连接进行排队。超过这个限制,服务端会退化到采用普通的 TCP 握手流程。这是为了减少资源耗尽攻击:Tcp Fast Open 可以在第一次 SYN 的时候发送 HTTP 请求,而服务端会校验 Fast Open Cookie(FOC),如果通过就开始处理请求。如果不加限制,恶意客户端可以利用合法的 FOC 发送大量请求耗光服务端资源。关于 Tcp Fast Open 的更多信息,可以参看 RFC7413。
reuseport
Nginx 在 1.9.1 版本中加入了 reuseport 功能,表示 Nginx 开始支持 TCP 的 so_reuseport 选项。关于这部分,可参看 官方文档
Gzip 压缩
http {
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_buffers 16 10k;
gzip_comp_level 3;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
gzip_disable "msie6";
gzip_http_version 1.0;
}
关于 gzip 压缩的更多说明,可以看我的 这篇帖子
缓存
缓存是很常见的优化手段,缓存手段也很多,本文列举出本博客使用的几种方案:
proxy_cache
用于对 proxy_pass
的缓存
http {
proxy_cache_path /home/nginx/proxy_cache/cache levels=1:2 keys_zone=proxycache:60m max_size=120m inactive=2h use_temp_path=on;
proxy_temp_path /home/nginx/proxy_cache/temp;
proxy_cache_key $host$uri;
}
server {
...
location / {
proxy_cache proxycache;
proxy_cache_valid 304 2h;
proxy_cache_valid 404 2h;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
proxy_cache_use_stale updating error timeout invalid_header http_500 http_502;
}
}
首先在全局配置 http
块内配置 proxy_cache 的路径(path)、空间名(keys_zone)、缓存上限、生成 key 规则,然后在站点配置中需要使用 proxy_cache 进行剩下的配置。上面我以 location / 作为示例。关于 proxy_cache 的更多说明,可以看我的 这篇文章
open_file_cache
缓存被频繁访问的文件相关的信息
open_file_cache max=2048 inactive=1d;
open_file_cache_valid 1d;
open_file_cache_min_uses 5;
open_file_cache_errors off;
其中:
max
缓存中的最大文件描述符数量inactive
存活时间,经过多长时间文件没被请求后清理缓存min_uses
在 inactive 时间段内,日志文件使用次数小于该值后,清理缓存valid
缓存的有效信息的检查频率
HTTP 强缓存
有一种缓存机制是,服务端通过响应头告诉浏览器,在哪个时间点之前(Expires),或在多长时间之内(Cache-Control: Max-age=…),不要再请求服务器了。这个机制通常称之为 HTTP 强缓存
。
一旦资源被判强缓存规则后,再次访问资源会完全没有 HTTP 请求(Chrome 开发者工具的 Network 面板依然会显示请求,但会注明 from cache;Firefox 的 Firebug 也类似,会注明 BFCache),这能够大幅提升性能。所以我们一般会对 CSS、JS、IMG 等资源使用强缓存。
开启强缓存,需要配置如下:
location ~ ^/static/ {
root /home/site/static;
etag on;
expires 2h;
}
HTTPS 优化
ssl_session_tickets on;
ssl_session_ticket_key ~/ssl_session_ticket.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate ~/ocsp.cer;
resolver 208.67.222.222 valid=300s;
resolver_timeout 5s;
这部分配置包含两部分内容:TLS 会话恢复
和 OCSP Stapling
关于 OCSP Stapling,可以参看 我的这篇文章
TLS 会话恢复的目的是简化 TLS 握手,它包含两种方案:Session Cache
和 Session Ticket
,这俩都是将之前握手的 Session 存起来,供后续连接使用。
所不同的是,Session Cache 将缓存丢在服务端,占用服务端资源;而 Session Ticket 丢在客户端,不占用服务端资源,而是对客户端提出缓存要求,这对客户端浏览器的兼容性提出了要求。目前主流浏览器普遍支持 Session Cache,而 Session Ticket 的支持度较一般。
在以上配置中,出现了一个 ssl_session_ticket.key
,这个文件是用于让多台机器使用相同的 key 文件,否则 Nginx 会使用随机生成的 key 文件,无法复用 Session Ticket,降低性能。对于单服务器站点,此文件无需配置。可执行以下指令生成该文件:
openssl rand 48 > ssl_session_ticket.key
至此,本博客 Nginx 配置(系列二)之优化篇,就告一段落了。当然本文中还有些地方没有点的很细的,会在之后的完整篇中进行注释。