QUIC是Quick UDP Internet Connections的缩写,谷歌出品的传输协议,使用UDP替换TCP来支持HTTP通讯。UDP自己不是可靠传输, 经过在其上添加流控、校验等功能,QUIC能够实现可靠传输,并且相比于TCP,它的流控功能在用户空间而不在内核空间,那么使用者就 不受限于CUBIC或是BBR,而是能够自由选择,甚至根据应用场景自由调整优化。html
QUIC为现有 tcp + https + http2
组合存在的诸多问题提供了解决方案:nginx
最新版的Chrome浏览器默认启用QUIC协议,只要后端服务器支持,Chrome就会使用QUIC协议。如今谷歌自家的大部分网站都使用了QUIC协议。git
不改变现有Web服务架构,咱们能够经过在内网添加一层反向代理,快速启用QUIC协议。这样,对于支持QUIC的客户端,使用QUIC协议改善外网通讯, 对于不支持QUIC的客户端,依旧沿用TCP通讯,并且就算这个反向代理挂掉了,Chrome浏览器还能够切回TCP通讯,没有增长服务中断风险。github
既然谷歌自家的网站已经启用了QUIC,咱们能够访问试试看。怎么知道打开的网站是否走了QUIC协议呢,咱们能够经过wireshark抓包验证,但还有 更方便的方法,直接用Chrome提供的工具,主要有三种方法:chrome
开发者工具Security选项卡后端
用Chrome浏览器打开谷歌官网www.google.com.hk ,按F12打开 开发者工具,切换到Security选项卡,刷新网页后选择左侧一个源站,能够看到 它使用的协议:浏览器
Chrome插件: HTTP/2 and SPDY indicator
缓存
从Chrome应用商店搜索插件名字能够下载,它用不一样颜色标识当前网站使用的是HTTP(灰色),HTTP2(蓝色)或者QUIC(绿色)服务器
网络调试页 chrome://net-internals
网络
Chrome还提供一个url用于调试网络状态,在浏览器中访问 chrome://net-internals/
地址,或者点击上述插件的小图标便可进入。 这里提供了很是丰富的监控和调试功能,咱们重点须要关注QUIC页面和Alt-Svc页面。
点击左栏的QUIC能够查看浏览器QUIC的版本配置以及QUIC会话。
点击左栏的Alt-Svc能够查看站点QUIC的端口、超时等状况。本页面的一个示例以下表:
| --------------Server -------------------| Alternative Service -------------| | ------------------------------------------ | ---------------------------------------- | | `https://client4.google.com` | quic :443, expires 2018-04-18 16:54:41 | | `https://zabbix.test.com` | quic :443, expires 2018-03-20 16:53:30 (broken) |
能够看到client4.google.com这个域名启用了QUIC协议,在UDP 443端口,后面是缓存超时。特别须要注意的是,zabbix.test.com这个地址, 它的最后有个(broken),意思是说虽然这个网站宣称本身支持QUIC协议,即有响应头 Alt-Svc: quic:443
,可是浏览器发出的QUIC请求 未获得响应。这种状况有多是防火墙屏蔽了UDP 443端口,也多是后端的QUIC服务挂了。
Chrome浏览器初次发出QUIC请求会使用的赛跑的方式,同时发出TCP和QUIC的请求,那个先返回就用哪一个,确认QUIC服务可用以后,后续请求 直接使用QUIC协议。可是,若是发现QUIC通道不可用了,它就把它标记为(broken),切回TCP链接。
QUIC是谷歌的,chromium中的QUIC实现算是官方实现,保证QUIC版本最新,但整个项目代码量太大,网络模块依赖较多, 又使用了本身的一套编译工具,若是本身从中剥离QUIC协议栈也比较麻烦。
chromium提供的C++接口很底层,须要本身实现会话、链接和流的管理,反向代理接收QUIC请求以后,须要构造UrlRequest发日后端。 要实现这些功能,还要先了解chromium的线程、消息循环、智能指针等一系列基础构件的使用方法,比较复杂,好在网上能找到一个样例。 这是一个尚在审核的提交 ,未来有望合入chromium主分支,能让用户快速启用QUIC尝鲜试用。
从chromium剥离的一个QUIC协议部分,可是其github主页已宣布再也不支持,仅做实验使用。
goquic封装了libquic的go语言封装,而libquic也是从chromium剥离的,好几年不维护了,仅支持到QUIC 36, goquic提供一个反向代理,测试发现因为QUIC版本过低,最新chrome浏览器已没法支持。
quic-go是彻底用go写的QUIC协议栈,开发很活跃,已在 Caddy 中使用,MIT许可,目前看是比较好的方案。它的接口和goquic接口 很相似,能够参考goquic反向代理的 代码 ,把QUIC部分替换为quic-go便可。最简单的实现方法,初始化一个反向代理handler 直接调用h2quic.ListenAndServeQUIC,主要代码以下:
import ( "net/http/httputil" "github.com/lucas-clemente/quic-go/h2quic" ) proxyHandler := httputil.NewSingleHostReverseProxy("localhost:80") err = h2quic.ListenAndServeQUIC(addrStr, cert, key, proxyHandler)
要编译这个反向代理,须要把整个chromium项目下载下来,能够按照 教程 操做,而后checkout这个 包含代理的提交 ,用ninja编译, 编译时只选择 quic_server
和 quic_client
便可。这个反向代理的实现,在 quic_server
的基础上加了一个启动选项 --mode=proxy
来开启反向代理模式,好比原来的服务在本机的80端口,使用原来的证书和私钥启动反向代理:
./quic_server --mode=proxy --quic_proxy_backend_url=http://localhost --certificate_file=leaf_cert.pem --key_file=leaf_cert.pkcs8
启动以后可使用QUIC测试客户端链接试试看:
./quic_client --host=127.0.0.1 --port=6121 https://www.example.org/index.html --disable-certificate-verification
第一次http请求仍是会从TCP端口先到达原始服务器,经过在响应中添加Alt-Svc头告诉客户端可以支持QUIC, 以nginx为例,在配置文件的http块中添加:
add_header Alt-Svc 'quic=":443"'
这时候用Chrome浏览器去访问你的网站,就可使用QUIC协议了。
根据上面介绍的方法,去Chrome浏览器中验证一下,若是指示器不是绿色的,能够点开看看是否(broken)了,尝试抓包查找网络缘由,调整防火墙策略。
移动互联网时代,光依靠Chrome浏览器可不行啊,谷歌提供了 cronet ,它是chromium网络协议栈的封装,能够用于Android和iOS平台,很方便 集成到手机APP中。 这里 能够下载编译好的cronet库。
2018-03-19 周一