今天上班偷闲逛 v 站时感受到了一阵强烈的安利风,好像所有个人站都已经从 HTTP/1.1 升级到了 HTTP/2 。呵呵,跟风也要讲基本法!立即着手升级工作。 上 Google 搜索关键字,才知道自己已经滞后了6个月,Nginx 从1.9.5版本开始已经加入了对 HTTP/2 的官方支持 Nginx Open Source 1.9.5 Released with HTTP/2 Support。这篇文章里也提到了 Nginx 从 1.9.5 开始,会停止对SPDY的支持,同时移除 Nginx 的 SPDY 模块。OK,看明白了之后,剩下的工作就简单了,升级 Nginx,开启 HTTP/2。

挂着小站的服务器上跑着的 Nginx 一直是 Nginx1.8.x,看了一眼 conf 文件,没有 SPDY 的参数设置,可以平滑升级到 1.10.0了。由于 Nginx1.10.0 发布在 mainline 上,如果想采用 apt 方式升级,还需要配置下 source 源。先安装 Nginx 的 apt 源的签名key,把 key 添加进 apt 源。

sudo apt-key add nginx_signing.key

修改/etc/apt/sources.list,在文件后追加 nginx mainline 的 deb 包源和 deb-src 源

deb http://nginx.org/packages/debian/ codename nginx
deb-src http://nginx.org/packages/debian/ codename nginx

此处的 codename 是系统版本的别称,比如我的服务器系统版本是 Debian 8,别名是 jessiecodename 即为 jessie。更新系统,Nginx 顺利升级到1.10.0

nginx version: nginx/1.10.0
built by gcc 4.9.2 (Debian 4.9.2-10)
built with OpenSSL 1.0.1k 8 Jan 2015
TLS SNI support enabled
configure arguments:
--prefix=/etc/nginx
--sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--pid-path=/var/run/nginx.pid
--lock-path=/var/run/nginx.lock
--http-client-body-temp-path=/var/cache/nginx/client_temp
--http-proxy-temp-path=/var/cache/nginx/proxy_temp
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
--http-scgi-temp-path=/var/cache/nginx/scgi_temp
--user=nginx
--group=nginx
--with-http_ssl_module
--with-http_realip_module
--with-http_addition_module
--with-http_sub_module
--with-http_dav_module
--with-http_flv_module
--with-http_mp4_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_random_index_module
--with-http_secure_link_module
--with-http_stub_status_module
--with-http_auth_request_module
--with-mail
--with-mail_ssl_module
--with-file-aio
--with-http_v2_module
--with-ipv6
--with-threads
--with-stream
--with-stream_ssl_module
--with-http_slice_module

可以看到 Nginx 已经把 1.8.x 时代的 Nginx 参数列表里的 --with-http_spdy_module 替换为 --with-http_v2_module,而这个 module 就是开启 HTTP/2 支持的模块。

修改 /etc/nginx/conf.d/xxx.conf 站点配置文件,在 443 端口监听的 server 设置里加上 http2 参数,80 端口访问强制跳转 https

server {
    listen 443 ssl http2 default_server;
}
server {
    listen 80;
    location / {
        return 301 https://$host$request_uri;
    }
}

改造的同时,我顺便把 SSL 证书换成 Comodo PositiveSSL。重新载入 Nginx 配置sudo service nginx reload。迫不及待的打开小站测试,然后呵呵哒,Chrome 返回 not available 的错误信息

This webpage is not available
ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY

原来在 Nginx 的站点配置里有一行参数 ssl_prefer_server_ciphers on;,如果开启了这个选项,那么当 Nginx 配置的 SSL ciphers 不支持 HTTP/2 时,就会发生上述错误,浏览器会拒绝该 HTTP/2 连接请求。所以需要把站点配置里的 ciphers 参数改成支持 HTTP/2 的设置

ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !kECDH !DSS !MD5 !EXP !PSK !SRP !CAMELLIA !SEED';

好了,小站顺利打开,检查下是否走的 HTTP/2 在 protocol 栏看到协议已经是 h2 了,表明开启 HTTP/2 成功。

对本站的小幅改进就到这里完工了。计划下周在工作之余,一锅乱炖 HTTP/1.1 和 HTTP/2,一直以来对HTTP协议这块的认识很欠缺,论一个 Web 开发者的自我修养……