扯一下
都知道 HTTP 协议都是 Client Request,然后 Server Response 这种一来一回的模式,并且一次请求都要重开一个连接.而 HTTP/2 的第一大特性就是真正意义上的复用一个链接,这减轻了服务端的性能压力;然后 HTTP/2 PUSH 这可以由服务端主动同时推送多个资源,大大加快了一个有大量资源页面的打开速度.
网上有好多关于HTTP/2的介绍,前不久 Nginx 终于宣布在 1.13.9 起加入 HTTP/2 PUSH 的支持,HTTP 服务端的主动推送,
如果是手动编译 Nginx 程序的话,需要添加参数--with-http_v2_modul
,这样才可以启用ngx_http_v2_module模块.而我这使用的 Nginx 官方的 Docker Image: nginx:alpine
,重新 docker pull nginx:alpine
更新最新的即可.
这次加入了 3 个参数:
Syntax: http2_max_concurrent_pushes number;
Default:
http2_max_concurrent_pushes 10;
Context: http, server
This directive appeared in version 1.13.9.
很明显,这个是限制 Server 侧主动推送资源时的并发上限值.
Syntax: http2_push uri | off;
Default:
http2_push off;
Context: http, server, location
This directive appeared in version 1.13.9.
这个http2_push
是指定要主动推送的资源,比如说指定了root /var/www/site/
为网站根目录,想要主动推送网站根目录下的 JS 文件,绝对路径为/var/www/site/js/jquery.js
和/var/www/site/js/diy.js
, 则可以写成:
http2_push /js/jquery.js;
http2_push /js/diy.js;
Syntax: http2_push_preload on | off;
Default:
http2_push_preload off;
Context: http, server, location
This directive appeared in version 1.13.9.
这个http2_push_preload
是为了解决动态页面下的资源推送问题.后端服务在响应请求时,在响应的Header中加入Link
字段,然后 Nginx 拿到后就会主动推送 Link
中标记的资源,这个是W3C制定的 HTTP/2 协议标准中的一项功能.
显然,相较于http2_push
,明显http2_push_preload
更给力.因为如果你要用http2_push
,先不说资源变动的问题,就说你一项项手动添加,都是个麻烦事.
WordPress设置
好的,不扯.
我去年就把博客转到 Docker 容器中运行了,现在docker-compose.yaml
的配置大致如下:
version: '2'
services:
db:
image: mysql:latest
restart: always
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
wordpress:
depends_on:
- db
image: wordpress:fpm
container_name: wordpress
restart: always
logging:
options:
max-size: "2m"
max-file: "5"
volumes:
- ./wordpress:/var/www/html
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_NAME: wordpress
nginx:
depends_on:
- wordpress
image: nginx:alpine
restart: always
container_name: nginx
logging:
options:
max-size: "2m"
max-file: "5"
ports:
- "80:80"
- "443:443"
volumes:
- ./wordpress:/var/www/html
- ./conf/default.conf:/etc/nginx/conf.d/default.conf
编辑给 Nginx 的default.conf
文件,直接在server
段内添加http2_push_preload on
:
server {
listen 443 ssl http2 fastopen=3 reusport;
server_name xxx;
# ...
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
# ...
http2_push_preload on;
# ...
}
最后编辑 WordPress 使用的主题中的 functions.php
,添加如下内容:
# this for http2 push preload
function add_http2_push() {
push_res = array(
# 这里要注意,如果资源超过了 10 个, 那么要将参数 http2_max_concurrent_pushes 改大
# 并且如果是css文件的话,并不建议push,除非css真的大且多,因为浏览器拿到页面的第一时间就去获取css文件,因此延迟是可以接收的,而js文件的话,可以加属性里添加 async 与 defer 进行异步和延后加载.
'</wp-includes/css/dist/block-library/style.min.css?ver=1.2.3>; as=style; rel=preload',
'</wp-includes/js/wp-emoji-release.min.js?ver=1.2.3>; as=script; rel=preload',
'</wp-content/themes/jinrishici.js>; as=script; rel=preload',
'</wp-includes/js/wp-embed.min.js?ver=1.2.3>; as=script; rel=preload'
);preload_link = join(', ', push_res );
header('link: '.preload_link);
}
add_action( 'send_headers', 'add_http2_push' );
后记
仔细研究了一番 Nginx 的 HTTP/2 ,目前 Nginx 的转发代理却未能支持 HTTP/2(不是stream模式的TCP反代),并且看官方的回复也不准备支持,所以说大概率也不会支持 H2C(HTTP/2 over TCP).
这个功能其实很重要,Nginx 反向代理的超高性能使得它的用户数十分庞大,而许多后端项目在传输中都希望开启HTTP/2,如果能加入 HTTP/2 流量转发的支持,那么可以直接在 Nginx 这中间层进行一些自定义的操作,比如 Header 的自定义动作,又或者一些统计什么的.
BTW, Apache 和 Caddy 是支持 HTTP/2 协议的流量转发代理.并且,gRPC(基于HTTP/2 )的传输代理却早在Nginx 1.13.10中被支持了. 但是真的很难理解 Nginx 开发者是怎么想的.