Web服务器快速启用QUIC协议

QUIC简介

QUIC是Quick UDP Internet Connections的缩写,谷歌出品的传输协议,使用UDP替换TCP来支持HTTP通讯。UDP自己不是可靠传输, 经过在其上添加流控、校验等功能,QUIC能够实现可靠传输,并且相比于TCP,它的流控功能在用户空间而不在内核空间,那么使用者就 不受限于CUBIC或是BBR,而是能够自由选择,甚至根据应用场景自由调整优化。html

QUIC为现有 tcp + https + http2 组合存在的诸多问题提供了解决方案:nginx

  • 使用缓存,减少握手延迟
  • 改善拥塞控制,拥塞控制从内核空间到用户空间
  • 多路复用中避免head-of-line堵塞,多路流互不影响
  • 前向纠错,减小重传
  • 链接平滑迁移,如手机从4G切到Wifi,应用不掉线

QUIC应用

最新版的Chrome浏览器默认启用QUIC协议,只要后端服务器支持,Chrome就会使用QUIC协议。如今谷歌自家的大部分网站都使用了QUIC协议。git

不改变现有Web服务架构,咱们能够经过在内网添加一层反向代理,快速启用QUIC协议。这样,对于支持QUIC的客户端,使用QUIC协议改善外网通讯, 对于不支持QUIC的客户端,依旧沿用TCP通讯,并且就算这个反向代理挂掉了,Chrome浏览器还能够切回TCP通讯,没有增长服务中断风险。github

输入图片说明

Chrome调试

既然谷歌自家的网站已经启用了QUIC,咱们能够访问试试看。怎么知道打开的网站是否走了QUIC协议呢,咱们能够经过wireshark抓包验证,但还有 更方便的方法,直接用Chrome提供的工具,主要有三种方法:chrome

  1. 开发者工具Security选项卡后端

    用Chrome浏览器打开谷歌官网www.google.com.hk ,按F12打开 开发者工具,切换到Security选项卡,刷新网页后选择左侧一个源站,能够看到 它使用的协议:浏览器

    输入图片说明

  2. Chrome插件: HTTP/2 and SPDY indicator缓存

    从Chrome应用商店搜索插件名字能够下载,它用不一样颜色标识当前网站使用的是HTTP(灰色),HTTP2(蓝色)或者QUIC(绿色)服务器

  3. 网络调试页 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链接。

开源实现

  • Chromium

    QUIC是谷歌的,chromium中的QUIC实现算是官方实现,保证QUIC版本最新,但整个项目代码量太大,网络模块依赖较多, 又使用了本身的一套编译工具,若是本身从中剥离QUIC协议栈也比较麻烦。

    chromium提供的C++接口很底层,须要本身实现会话、链接和流的管理,反向代理接收QUIC请求以后,须要构造UrlRequest发日后端。 要实现这些功能,还要先了解chromium的线程、消息循环、智能指针等一系列基础构件的使用方法,比较复杂,好在网上能找到一个样例。 这是一个尚在审核的提交 ,未来有望合入chromium主分支,能让用户快速启用QUIC尝鲜试用。

  • proto-quic

    从chromium剥离的一个QUIC协议部分,可是其github主页已宣布再也不支持,仅做实验使用。

  • goquic

    goquic封装了libquic的go语言封装,而libquic也是从chromium剥离的,好几年不维护了,仅支持到QUIC 36, goquic提供一个反向代理,测试发现因为QUIC版本过低,最新chrome浏览器已没法支持。

  • quic-go

    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

nginx配置

第一次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 周一

相关文章
相关标签/搜索