本文主要介绍HTTP2.0的新特性 以及ngnix或tomcat下如何配置使满足HTTP2.0协议
HTTP2.0新特性:
HTTP2.0相比HTTP1.1可以给用户带来更佳的用户体验,原因这里不会一一详细介绍,只列举了几项,如有兴趣研究的童鞋请移步 官方RFC文档。
1.新增二进制分帧
HTTP
协议从0.9
版本开始不断增加新的功能特性,但长远来看都是 向前兼容
的,HTTP 2.0
在 应用层
跟 传输层
之间增加了一个 二进制分帧层
,从而能够达到 “在不改动HTTP的语义、HTTP方法、状态码、URI及首部字段的情况下,突破HTTP 1.1的性能限制,改进传输性能,实现低延迟和高吞吐量。”
如上图所示,在 二进制分帧层
上, HTTP 2.0
会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码,其中 HTTP 1.1
的首部信息会被封装到 Headers
帧,而 request body
被封装到 Data
帧里面。
2.压缩头部
如下图所示:HTTP 2.0
在 客户端
和 服务端
使用 首部表 来跟踪和存储之间发送的 键-值
对,对相同请求而言不需要再次发送请求和相应发送,通信期间几乎不会改变的通用 键-值
(如:用户代理、可接受的媒体类型)只需发送一次。
Headers
帧里面,新增或修改的 首部帧
会被追加到 首部表3.多路复用
记得大学 计算机网络
跟 计算机组成原理
这两门课都讲到了 多路复用
这个概念,当时一知半解(可能是老师讲得太抽象了o(╯□╰)o)。相比一个入了门的前端开发在谈到 性能优化
的方法时都可以轻轻松松列举如下几点:
然后我们可以自豪地晒出下面的代码片段:
<html> <head> <link rel="stylesheet" href="xxx.cdn.com/??a.css,b.css" /> head> <body> ... <script src="xxx.cdn.com/??a.js,b.js">script> body> html> |
但 HTTP 2.0
的 多路复用
让我们回到了最原始最自然的写码状态,先看下图:
对 HTTP 1.1
而言,浏览器通常有链接的限制,即使开启多个链接,也需要付出相应的代码,而 多路复用
允许同时通过单一的 HTTP 2.0
连接发起多重的 请求-相应
消息。
这意味着 HTTP 2.0
的通信都在一个连接上完成了,这个连接可以承载任意数量的 双向数据流 ,直观来说,就是我们又可以开开心心写出下面代码:
<html> <head> <link rel="stylesheet" href="a.css" /> <link rel="stylesheet" href="b.css" /> head> <body> ... <script src="a.js">script> <script src="b.js">script> body> html> |
4.请求优先级
既然所有资源都可以并行交错发送,会不会导致下面这种情况呢?
浏览器: 服务器,请给我需要的CSS文件
服务器: Biu,发送图片中…
浏览器: 服务器,请给我需要的JS文件
服务器: Biu,发送图片中…
浏览器: 服务器,你TM的倒是给我发送我需要的CSS文件跟JS文件呀!
这个时候 HTTP 2.0
的 请求优先级
特性出场了,在每个 HTTP 2.0
的 流
里面有个 优先值 ,这个 优先值 确定着客户端跟服务器处理不同的 流
采取不同的 优先级策略 ,高优先级的应该优先发送,但这不会绝对的(绝对等待会导致 首队阻塞
问题)。在分配处理资源和客户端与服务器间的宽带,不同优先级的混合都是必须的。
5.服务器提示
一般情况下,客户端需要请求啥东西告诉服务器,然后服务器返回对应资源回到客户端,这也是请求很慢的原因之一。HTTP 2.0
新增加 服务器提示
,可以先于客户端检测到将要请求的资源,提前通知客户端,服务器不发送所有资源的实体,只发送资源的 URL
。客户端接到提示后会进行验证缓存,如果发现需要这些资源,则正式发起请求。
这个技术跟我们常用的 预加载
技术实现差不多,但 服务器提示
是通过 HTTP Link Header
和 Link Prefetching
语义重叠的部分来实现的。
打开 Nginx官网 可以看到其中有一条新闻如下:
显然,Nginx
是已经有了一个 ngx_http_v2_module
模块用来支持 HTTP 2.0
的,但是还不是稳定版,所以想要尝鲜那就需要 手动升级Nginx 。
科普时间到此结束,下面就让我们正式进入今天的主题: 一步步实现Nginx配置HTTP 2.0
。
下面内容有条件的同学请对比实践操作,体会更深。
我将从下面几步来介绍:
SSL/TLS
安全证书在开始我们的任务之前,请先下载 OpenSSL,pcre,Zlib 跟 Nginx源码 ,并且全部解压到同一个目录,假设为 nginx-build
,这时候的代码结构如下:
nginx-build nginx-1.9.14 pcre-8.38 openssl-1.0.2g zlib-1.2.8 |
若之前用
brew
安装过Nginx
,请先执行brew uninstall nginx
卸载。
准备工作做好之后���打开 Terminal
切换到上面的 nginx-build
目录,然后执行下面命令编译Nginx:
cd nginx-1.9.14 sudo ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-pcre=../pcre-8.38 --with-openssl=../openssl-1.0.2g --with-zlib=../zlib-1.2.8 --with-http_v2_module > 输入管理员密码然后回车 |
配置源码成功之后,为了避免 make
失败,因为我失败了(可能是人品不好…),反正我 make
的时候报了下面的错误:
所以建议大家跟我一样先修改一个配置文件,如下命令(相对于nginx-build
目录):
cd nginx-1.9.14/objs sudo vi Makefile > 输入管理员密码然后回车 |
接着回到nginx-build
目录,然后执行下面命令编译:
cd nginx-1.9.14 sudo make && make install |
如果没有报错那就编译成功,在终端试试 sudo nginx
启动,然后打开 http://localhost 能看到欢迎页,然后在终端输入 nginx -v
看到 nginx version: nginx/1.9.14
。
SSL/TLS
安全证书要配置 HTTP 2.0
就需要启动 HTTPS
,那就需要生成一个 SSL/TLS
证书,而 OpenSSL
正好可以做这件事情,买不起证书但自己造一个来临时用还是可以的,直接执行下面命令:
# 切换到nginx的根目录(我这里是/usr/local/nginx,请根据上一步编译时候指定的--prefix对应修改) cd /usr/local/nginx cd conf # 利用openssl命令生成公钥跟密钥 openssl genrsa -des3 -passout pass:x -out cert.pass.key 2048 openssl rsa -passin pass:x -in cert.pass.key -out cert.key openssl req -new -key cert.key -out cert.csr openssl x509 -req -days 365 -in cert.csr -signkey server.key -out cert.crt # 将crt跟key合并生成pem文件 cat server.crt server.key > server.pem # 删除掉我们不需要用到的文件 rm -rf cert.crt cert.csr |
离成功之后一步之遥了,接下来就是最重要的一步,配置Nginx支持HTTP 2.0,修改Nginx配置文件/usr/local/nginx/conf/nginx.conf
:
1.将所有HTTP请求重定向到HTTPS请求
location / { return 301 https://$host$remote_port$request_uri; } |
2.配置HTTPS server
server { listen 443 ssl http2 default_server; server_name localhost; ssl_certificate cert.pem; ssl_certificate_key cert.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; # 我用原始的下面这段启动报错了,所以注释掉改用了后面那段 #ssl_ciphers HIGH:!aNULL:!MD5; ssl_ciphers 'CHACHA20:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4;'; ssl_prefer_server_ciphers on; location / { root html; index index.html index.htm; } } |
可以注意到上面 HTTPS
的配置比之前多了一个 http2
,这就是 ngx_http_v2_module
模块,若没有安装该模块启动一样会报错。
3.重启服务器
配置完成之后,重新启动服务器即可:
sudo nginx -s reload |
4.预览
打开 http://localhost ,自动跳转到 https://localhost ,ok完成!
系统环境:
CentOS release 6.5 (Final) x64
JDK 1.8.0_92
apache-tomcat-9.0.0.M6.tar.gz
apr-1.5.2.tar.gz
apr-util-1.5.4.tar.gz
openssl-1.0.2h.tar.gz
本人在安装的过程中,碰到了很多坑,尤其是需要注意的是,编译安装tomcat-native的时候,需要指定openssl,而编译安装openssl的时候,需要指定shared
操作步骤如下
一:安装apr
tar -xvf apr-1.5.2.tar.gz
cd apr-1.5.2
./configure --prefix=/usr/local/apr
make
make install
二:安装apr-util
tar -xvf apr-util-1.5.4.tar.gz
cd apr-util-1.5.4
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
make
make install
三:安装openssl
tar -xvf openssl-1.0.2h.tar.gz
cd openssl-1.0.2h
./config shared --prefix=/usr/local/openssl-1.0.2h
make depend
make
make install
注意这里必须指定shared
四:安装
tar -xvf apache-tomcat-9.0.0.M6.tar.gz
cd apache-tomcat-9.0.0.M6/bin
tar -xvf tomcat-native.tar.gz
cd tomcat-native-1.2.7-src/native
./configure --prefix=/usr/local/tomcat-native --with-apr=/usr/local/apr --with-java-home=/usr/local/jdk1.8.0_92 --with-ssl=/usr/local/openssl-1.0.2h
make
make install
注意这里的--with-ssl 必须指定
五:配置ld
vim /etc/profile
export LD_LIBRARY_PATH=/usr/local/tomcat-native/lib:$LD_LIBRARY_PATH
source /etc/profile
六:生成证书
cd apache-tomcat-9.0.0.M6
mkdir ssl
cd ssl
openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -new -x509 -key server.key -out ca.crt -days 3650
七:配置tomcat
cd apache-tomcat-9.0.0.M6/conf
vim server.xml
找到如下内容
把这一段内容,取消注释
并改成如下内容
保存退出,启动tomcat