前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HTTP/3 初体验

HTTP/3 初体验

作者头像
李俊鹏
发布2020-06-15 16:20:58
1.9K0
发布2020-06-15 16:20:58
举报
文章被收录于专栏:运维研习社运维研习社

HTTP协议经过发展,目前HTTP2.0作为主流HTTP协议,已经得到一定普及,虽然国内仍然有很多连HTTPS都没上的网站,但不影响HTTP协议的发展。

HTTP2.0我们知道相较于HTTP1.1版本的协议,进行了很多的优化,现在HTTP-over-QUIC出了也有一段时间了,虽然还是实验性协议,但是IETF HTTP和QUIC工作组主席Mark Nottingham正式提出将HTTP-over-QUIC重命名为HTTP/3.0到现在已经有一年多的时间了,所以HTTP-over-QUIC成为HTTP/3.0算是没跑了,所以还是早点认识一下这个新版本的协议

QUIC全名是(Quick UDP Internet Connections),它是google在2013年开发实现的

我们都知道,TCP和UDP最本质的区别在于可靠传输,HTTP2.0及之前的协议建立在TCP上,TCP为了达到可靠传输,必须要有确认机制,需要来回握手确认来建立链接,即便HTTP2.0中做了很多优化,但仍然摆脱不了TCP的三次握手,而且TCP协议在处理包时是有严格顺序的,当其中一个数据包遇到问题时,TCP链接需要等待整个包重传之后才能继续进行,虽然HTTP2.0中通过多个stream,使得逻辑上一个TCP链接上的并行内容,进行多路数据传输,然而这中间没有关联的数据,当stream2的帧没有收到,后面stream1的帧也会因此阻塞

所以google在QUIC协议中基于UDP协议,跳出TCP协议,它是在两个端点之间创建链接,且支持多路复用,并且在设计之初就考虑希望能够提供等同于SSL/TLS层级的安全保障的同时,减少数据传输及创建链接时的延迟时间,双向控制带宽,从而达到更快速的体验,先通过一个动图直观对比下

接着看下QUIC有什么优势,已经通过什么方法解决TCP的一些限制及问题

新定义连接机制

在TCP连接中,一条TCP连接是由四元组标识的,分别是源IP、源端口、目的IP、目的端口,一旦一个元素发生变化时,就会断开重连,重新进行三次握手,导致一定的延时

在基于UDP的QUIC中,是在自己的逻辑里面维护连接的机制,不再是以四元组标识,而是以一个64位的随机数作为ID来标识,而且UDP是无连接的,所以当IP或端口变化的时候,只要ID不变,就不需要重新建立连接

新定义重传机制

在TCP连接中,为了保证可靠性,通过使用序号和应答机制,来解决顺序问题和丢包问题,如上面说到的,即便HTTP2.0使用stream的方式,也还是存在阻塞的问题

在TCP中,任何一个序号的包发过去,都要在一定时间内得到应答,超时之后,就会触发重传,重新发送这个序号的包,而RTO(重传超时时间)的计算相对复杂,现在都是通过自适应算法设定RTO的值,而这个计算的不准确会直接导致网络的吞吐量和网络资源利用率

在QUIC中,也有个序列号PN(Packet Number),是递增的,任何一个序列号的包,只发送一次,下次就要加1,根据Packet Number值就可以计算出是重传响应还是原始响应,这样可以准确计算RTT时间

但是有一个问题,就是UDP无连接,所以没法确认两个包是否是同样的内容,也就是没有办法确定发送出去的包是不是重传包,QUIC虽然基于UDP,但它也是一个可靠数据传输协议,所以QUIC又定义了一个offset概念,在发送的数据流里面有个偏移量offset,可以通过offset查看数据发送到了哪里,这样只有这个offset的包没有来,就要重发,如果来了,按照offset拼接成一个完整的数据流

对于重传,QUIC有个特性就是关键包短时间内发送多次,这样以确保重要的节点不被Delay

没有HOL的多路复用

QUIC的多路复用和HTTP2类似,在一条QUIC连接上可以并发发送多个HTTP请求,但是QUIC的多路复用比HTTP2有一个很大的优势,那就是QUIC一个连接上的多个stream之间没有依赖,这样,假如stream2丢了一个udp packet,也只会影响stream2的处理,不会影响stream2之前以及之后的stream的处理,这就很大程度上缓解了HOL阻塞的问题

当然并不是所有的QUIC数据丢失都不会受到HOL阻塞影响,比如QUIC使用Hpack压缩算法的时候,由于算法的限制,丢失一个头部数据时,可能遇到HOL阻塞

流量控制

UDP没有流量控制机制,由于QUIC的多路复用机制,其流量控制分为Stream和Connection两种级别的控制

Stream就可以理解为一条HTTP请求

Connection可以理解为一条TCP连接

具体的实现机制是

  • 通过window_update帧告诉对端自己可以接收的字节数,这样发送方就不会发送超过这个数量的数据
  • 通过BlockFrame告诉对端由于流量控制被阻塞了,无法发送数据

QUIC的流量控制和TCP的有点区别,TCP是使用了滑动窗口机制来进行流量控制,为了保证可靠性,窗口左边沿向右滑动的长度取决于已经确认的字节数,如果中间出现丢包,就算接收到了更大序列号的Segment,窗口也无法超过这个序列号,但是QUIC不同,就算此前有些Packet没有接收到,它的滑动只取决于接收到的最大偏移字节数

对于Connection级别的流量窗口,其接收窗口大小就是各个stream接收窗口大小之和

而在Connection中,不同的stream互相独立,不会引起HOL阻塞

所以在弱网环境下,QUIC优势更明显

HTTP/3.0综上所述,有这么多优点,必须要体验一下,下面介绍下Nginx支持HTTP/3.0

Nginx原生不支持HTTP/3.0,这里需要借助Cloudflare提供的一个补丁来让Nginx支持HTTP/3.0

这里因为要补丁编译安装,所以需要下载nginx源码包,我这里仍然用nginx1.17.7版本来测试,下载包解压包就不说了

接着通过git下载QUIC补丁

然后因为要用patch打补丁,所有通过yum安装patch

接着就开始打补丁

这里只有nginx1.16的补丁,我也不确定,看着是打上了,编译试一下

重要的是with-http_v3_module、openssl用quiche/deps下面的boringssl,另外就是--with-quiche指向quiche目录

接着make,这里因为没有cmake报了个错误,通过yum安装cmake3,

注意要用cmake3.0以上版本,所以用yum install cmake3,这个要开启epel源

然后重新make,这里还需要安装gcc-c++,cargo、golang环境,否则在编译boringssl的时候会报错,编译不过去

接着是漫长的等待,如果服务器性能好的话,可以用make -j加速编译

在后面使用cargo编译的时候,因为默认是creates.io的仓库,实在太慢了,所以这里建议更换为中科大的源,在/root/.cargo下面新建config文件,内容如下:

更多cargo的可以查看cargo中文社区

另外就是编译boringssl的时候,编译出的库为静态库,最后ld链接的时候无法连接,需要在nginx编译之后生成的objs/Makefile中修改cmake编译参数,设置为-fPIC,生成共享库,否则编译失败

之后即可编译成功

在objs下面将nginx二进制文件覆盖掉原来的nginx,开始配置nginx配置文件

在quiche中通过cargo构建客户端,通过http3-client测试请求

客户端请求

请求日志查看

抓包查看

如果是chrome浏览器开启QUIC

需要重启chrome才能生效

当然如果不想像我一样折腾,直接用docker就可以体验了

docker run -it -p 443:443 -p 443:443/udp \ -v $PWD/nginx.conf:/usr/local/nginx/conf/nginx.conf \ -v /root/cert/haid.com.cn.pem:/etc/ssl/certs/server.crt \ -v /root/cert/haid.com.cn.key:/etc/ssl/private/server.key \ nwtgck/nginx-http3

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档