为什么要使用HTTP/2

http/2作为新一代http协议,可以说是http/1.x的完全重构。

http/2重新定义了http数据包的格式,使用二进制格式的frame来进行传输(在http1.x中使用的是明文字符串),这个改动让http/2更加易于优化和扩展。

http/2支持多路复用,http1.x虽然也能做到在同一个tcp请求中并发进行数个http请求,但是请求是阻塞的(上一个请求取得响应前是得不到下一个请求的响应的),http/2在同一个tcp请求中可以完成所有http请求(非阻塞,后一个请求可以在前一个请求之前取得响应),并且同时实现流量控制以及优先级控制。

http/2对消息头使用了为http请求量身定做的HPACK压缩方案,这个压缩协议简单来说就是客户端和服务端同时维护一个hash表,将常用的消息头以Key-Value形式保存,传输时只传输Key即可,如在http请求中常用的"GET /index.html"用Key:1保存起来,那么在http/2的消息头中就只需要一个数字1即可(在http1.x要使用完整的字符串)。

http/2支持ServerPush,由服务端主动推送资源到客户端。

总结:对比http1.x,http/2的最大改进就是性能,同样的请求,http/2可以在更加短的时间内传输更少的数据来完成,目前主流的浏览器均已经支持了http/2,可以说是大势所趋。

HTTP/2官方链接 实现HTTP/2的项目列表

为什么使用HTTPS

https作为安全的http通道的作用家喻户晓,就不再赘述。

这里简述为什么使用http/2的同时要使用https。

实际上http/2协议包含了两个模式,一个是http/2,基于ssl加密,与https兼容,简称h2,另外一个是http/2 cleartext,也就是http/2明文模式,简称h2c,也就是我们现在一般使用的http。

虽然http/2设计了两种模式(nginx也支持这两种模式),但是各大浏览器厂商都默认抛弃了h2c模式,因此如果不使用https直接使用http2的话,大部分浏览器无法正常访问网页

因此未来h2c的使用场景估计将更多会用于内网服务器的通讯或者自制客户端。

事前准备

openssl : 需要1.0.2以上版本,由于HTTP/2需要ALPN扩展,而openssl是1.0.2以后才支持ALPN。

nginx : 需要1.9.5以上版本才支持http_v2_module,如果低于这个版本则需要重新编译nginx并且升级,另外nginx在编译的时候使用的openssl库也必须是openssl1.0.2以上版本才行,否则也需要重新编译nginx(如果编译nginx时openssl使用的是动态库模式理论上应该可以通过升级动态库然后reload nginx即可)。

参考资料:nginx_http_v2_module

由于阿里云的yum源自带的openssl版本最高只有1.0.1e,并且nginx编译openssl时使用的是静态编译模式,因此我选择的是直接重新编译升级nginx,顺便也升级了下系统的openssl库。以下是升级笔记,供参考。

编译和升级NGINX

1.更新依赖包(如zlib,pcre等)

yum update zlib
yum update pcre
...

2.到 openssl官网 找到需要的openssl版本并且下载解压

wget https://www.openssl.org/source/openssl-1.0.2k.tar.gz
tar xzvf openssl-1.0.2k.tar.gz

3.到nginx官网下载需要的nginx版本,然后编译。

wget http://nginx.org/download/nginx-1.10.3.tar.gz
tar xzvf nginx-1.10.3.tar.gz
cd nginx-1.10.3
#configure 编译参数根据个人需要做出调整 必须保留http_ssl_module http_v2_module
#推荐使用 nginx -V 命令来查看原本的nginx的编译参数
#注意 --with-openssl 参数后面跟的目录是刚刚下载解压的openssl源码目录
./configure --user=nobody --group=nobody --with-http_ssl_module --with-http_v2_module --with-pcre --with-pcre-jit --with-openssl=/root/package/openssl-1.0.2k
#只make 不要make install
make

4.编译完成后,需要将原本的nginx可运行文件备份,之后直接在源目录下使用 make upgrade 完成平滑升级。

参考资料: Upgrading Executable on the Fly (百度“nginx 平滑升级”也能找到许多类似资料)

如果make upgrade出错的话,也可以选择粗暴的方式直接kill 正在运行的nginx进程,然后直接重启新的nginx,但是这样做会丢失nginx正在处理的请求。

升级系统内的openssl(大概非必要)

1.到https://www.openssl.org/ 找到需要的版本

2.下载,解压,编译,安装

wget https://www.openssl.org/source/openssl-1.0.2k.tar.gz
tar xzvf openssl-1.0.2k.tar.gz
cd openssl-1.0.2k/
./config shared zlib-dynamic
make
make install

这里要注意的是,openssl默认的安装目录是/usr/local/ssl(当然也可以自己指定,我这里使用了默认的路径)

3.将老版本的openssl备份,并且将新版本软链到原位置

mv /usr/bin/openssl /usr/bin/openssl.old
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl

mv /usr/include/openssl /usr/include/openssl.old
ln -s /usr/local/ssl/include/openssl /usr/include/openssl

mv /usr/lib64/openssl/engines /usr/lib64/openssl/engines.old
ln -s /usr/local/ssl/lib/engines /usr/lib64/openssl/engines

rm /lib64/libssl.so
ln -s /usr/local/ssl/lib/libssl.so /lib64/libssl.so

echo "/usr/local/ssl/lib" >> /etc/ld.so.conf
ldconfig

Tips:由于每个系统的环境配置不尽相同,因此要建议使用whereis来确认自己的系统原本的openssl的路径。

nginx和openssl都准备好了以后,就可以进入下一个环节。

NGINX配置HTTPS以及HTTP2

1.获得SSL证书:免费 SSL 和 便宜 SSL 介绍

2.修改NGINX的对应的SERVER段配置

listen 443 ssl http2;
server_name www.cngal.org;

ssl on;
ssl_certificate certificate.crt;
ssl_certificate_key certificate.key;

这样就完成了NGINX的HTTPS以及HTTP2的NGINX服务器配置。

PS:实际情况当然不可能这么简单!毕竟运行中的网站切换HTTPS的话,大量的页面链接以及复数个子域名等都需要处理,因此会有好几个坑在这里,在这篇文章就不详细叙述了~之后再整理HTTPS配置以后网站的修改注意要点。

undefined

完成以后,使用firebug之类的调试工具查看http版本就能看到当前网站运行在什么http协议版本下了 :)