Tengine 准备
Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。
从2011年12月开始,Tengine成为一个开源项目,Tengine团队在积极地开发和维护着它。Tengine团队的核心成员来自于淘宝、搜狗等互联网企业。
大家可以通过Tengine官网 http://tengine.taobao.org/ 下载和安装最新版本。
如下演示为在 /work
目录下载编译,当前的版本是 2.3.2 最新版本请前往官网查看。
tengineVersion='2.3.2'
cd /work
wget http://tengine.taobao.org/download/tengine-$tengineVersion.tar.gz
gzip -d tengine-$tengineVersion.tar.gz
tar xvf tengine-$tengineVersion.tar
Brotli 准备
Brotli是一种通用无损压缩算法,它结合了LZ77算法的现代变体,哈夫曼编码和二阶上下文建模来压缩数据,其压缩率可与目前最好的通用压缩方法相媲美。 它的速度跟deflate算法差不多,但压缩率更高。官网地址:https://github.com/google/ngx_brotli
Brotli 压缩算法最典型的3特点:
- 针对常见的 Web 资源内容,Brotli 的性能相比 Gzip 提高了 17-25%;
- 当 Brotli 压缩级别为 1 时,压缩率比 Gzip 压缩等级为 9(最高)时还要高;
- 在处理不同 HTML 文档时,Brotli 依然能够提供非常高的压缩率。
另外,除了 IE 和 Opera Mini 之外,几乎所有的主流浏览器都支持 Brotli 算法。
cd /work
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli
git submodule update --init --recursive
若以上操作因网络问题超时失败,可以尝试用国内我在码云镜像的该项目仓库:
cd /work
git clone https://gitee.com/sang93/ngx_brotli.git
已含有deps
编译
cd tengine-$tengineVersion
./configure --with-http_v2_module --with-openssl-opt=enable-tls1_3 --add-module=/work/ngx_brotli
make && make install
参数说明:
- --with-http_v2_module 开启 HTTP/2
- --with-openssl-opt=enable-tls1_3 开启 TLS 1.3 支持
- --add-module=/work/ngx_brotli ngx_BroTli 扩展源码位置
若 ./configure
出错,则可能是需要安装pcre的devel包,pcre-devel。使用yum安装即可:(以下命令还带有ssl、zlib等依赖的安装)
yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel
安装目录为 /usr/local/nginx
找到 /usr/local/nginx/sbin/nginx -V
查看所有加载的模块
可以看到
[root@SSQ /work]# /usr/local/nginx/sbin/nginx -V
Tengine version: Tengine/2.3.2
nginx version: nginx/1.17.3
built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)
built with OpenSSL 1.1.1c FIPS 28 May 2019
TLS SNI support enabled
configure arguments: --with-http_v2_module --with-openssl-opt=enable-tls1_3 --add-module=/work/ngx_brotli
/usr/local/nginx/sbin/nginx start|stop|restart
启动和关闭ngix服务
更新配置
压缩相关
该处的配置建议在 http {}
内,方便配置到全站点。
其中 sendfile 参数用于开启文件的高效传输模式。同时将 tcp_nopush 和 tcp_nodelay 两个指令设置为 on ,可以防止网络和磁盘I/O阻塞,以提升Nginx工作效率。
配置样例如下:
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nodelay on;
tcp_nopush on;
keepalive_timeout 65;
# 压缩相关
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/x-javascript application/javascript application/xml application/xml+rss text/x-component application/xhtml+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;
brotli on;
brotli_min_length 1k;
brotli_buffers 4 16k;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript application/json application/x-javascript application/javascript application/xml application/xml+rss text/x-component application/xhtml+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;
# 代理相关
client_max_body_size 128m;
client_body_buffer_size 128m;
proxy_connect_timeout 900;
proxy_send_timeout 900;
proxy_read_timeout 900;
proxy_buffer_size 40k;
proxy_buffers 40 320k;
proxy_busy_buffers_size 640k;
proxy_temp_file_write_size 640k;
proxy_temp_path /tmp/proxy_temp_dir;
proxy_cache_path /tmp/proxy_cache_dir levels=1:2 keys_zone=cache_one:50m inactive=7d max_size=2g;
HTTP/2 和 TLS1.3
开启 HTTP/2 只需要 listen 443 ssl http2
即可。
HTTP/2 和 TLS1.3 放在 Server 中,一个完整的 server{}
如下:
server {
listen 443 ssl http2;
server_name sang.cool;
#证书
ssl_certificate server.pem;
ssl_certificate_key server.key;
#握手优化
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
keepalive_timeout 75s;
keepalive_requests 100;
#版本控制
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
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';
location / {
root html;
index index.html index.htm;
}
}
服务端推送 Preload
多路复用是 HTTP/2 的一个特性,那么如何启用服务端推送来加速网页资源的加载呢? W3C 提供了两种方案,一种是 HTTP 头部写推送的信息,一种是在 html 的头部写,具体的方法可以参考 Preload 相关文章 https://www.w3.org/TR/preload 。
为了后面修改和更新需要预加载的资源方便,这里演示采用的是写在 html 文件头部的方式。
只需要在 <header>
中加入需要预加载的资源文件即可,不同的文件,写法不同,更多的样例可以前往 W3C 网站查看。
<link rel="preload" href="/styles/other.css" as="style">
<link rel="preload" as="script" href="/js/utils.js" />
当然,写在 HTTP 的响应头中的,浏览器处理预加载的会比写在 header 中快。
这一块的改造,需要测试具体的效果,如果你的网站需要加载的资源文件过多的情况下,还是不太建议进行此优化的,大家可以做个具体的测试。
同时,需要注意的是,对于非本域的资源,在推送的时候,需要加上 crossorigin
属性,如:
<link rel="preload" href="https://cdn.domain.com/exp.css" as="style" crossorigin>
需要特别注意的是 字体文件无论是不是本域的,都需要加上 crossorigin
属性,否则会被重复加载,如:
<link rel="preload" as="font" href="/css/digit.woff2" type="font/woff2" crossorigin>
若只有部分预加载的话,可能会造成部分不进行预加载的文件加载开始时间太过靠后,造成整体加载完成时间变长。
总之还是一句话:看具体改造后的效果。
对于使用了使用了 CDN 或其他源站的资源文件的情况,可以做一下 DNS 预解析的优化。一般来说,HTTPS 站点使用外站资源最好还是使用支持 HTTPS 协议的,不然整个站点的安全小绿标就变灰啦,Chrome 浏览器会直接显示不安全。那么一个外站资源的请求,则需要经过 DNS → TCP → TSL ,这样用许多乱七八糟的外站资源也会使网站整体访问变慢,特别是加载了一些核心的 CSS 样式等资源文件的时候。
DNS 预解析可以提前解析之后可能会用到的域名,把解析结果缓存到系统中,这样就缩短DNS解析时间,那么网站的访问速度也会有所提高。包括淘宝的官网,使用了很多的其他站点的 CDN 资源,加了很多的 DNS 预解析设置,来提高前端的访问速度。
根据上图我们即可以发现,DNS 预解析其实很简单,与预加载资源类似,只需要添加一条 link 标签即可。
<link rel="dns-prefetch" href="//cdn.domain.com" />
重启并验证
在更新好 nginx 配置后,记得验证一下配置文件的情况:
/usr/local/nginx/sbin/nginx -t
可得如下反馈,即为没有问题
[root@SSQ nginx]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
若已添加系统服务,service nginx restart
即可。
[!WARNING]
若你的 conf 文件有多个 server 的配置,则需要每个 server 都一样的进行配置 TLS1.3 ,否则将无法开启成功。
如何验证我们配置的加密方法和TLS呢? 可以通过这个网站进行系统的测试 https://www.ssllabs.com/ssltest/index.html。
优化前
在优化前,内容加载 191ms 。
优化后
如下图,可见,优化后改进的 Brotli 压缩,数据更小,内容加载速度变为了 132ms。
启用了TLS1.3: