1、背景简述

最近做了一个网红街的商户收银系统:包含小商铺场景下用户微信扫码点餐H5、小程序、商家PAD点餐、排号、叫号、时间预测等,堂食多人扫桌码点餐、商家PAD点餐等。在前期的现场测试中发现该地区中国移动,中国电信4G、5G网络带宽低,抖动大。偶尔会出现用户端软件响应速度极慢。

2、大致结构

项目结构.png

3、当前策略

目前全站接入HTTP/2,目前服务器支持的技术如下:

(1)、多路复用:代替掉HTTP1.x的序列和阻塞机制。同域名下所有通信都在单个连接上完成。单个连接可以承载任意数量的双向数据流。数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

chromef12.png

(2)、Server Push:HTTP/2 规范中引入的一种新技术,即服务端在没有被客户端明确的询问下,抢先地 “推送” 一些网站资源给客户端(浏览器),该特性可以极大的改善页面访问效果。

(3)、头部压缩:HTTP/2在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值。

(3)、WebP:Google推出的一种同时提供了有损压缩与无损压缩的图片文件格式。能最高将图片大小缩减90%左右,非常适合web图片使用。

(4)、OCSP 装订缓存:服务器在 TLS 握手时会发送被缓存的OCSP响应,供用户验证,无需用户再向CA发送查询请求。极大地提高了 TLS 握手效率,节省了用户验证时间。

(5)、CDN:采用第三方厂商CDN服务来处理静态资源和页面缓存,能在用户访问时通过最近最优的节点去返回缓存资源,大大的优化了资源在网络传输中的效率。

4、优化方案

理论上如上操作即可极大的增强用户体验,但是仅仅是能提升正常网络状态下的用户体验。而针对高延迟,抖动大的弱网络环境仅仅做到上述策略还不够。

首先想到的是TCP和UDP两种协议的优缺点:

TCP:可靠、稳定,但是建连需要经过3次握手,相对繁琐、效率低且占用系统资源高。

UDP:效率高、快、轻量,占用系统资源较少,但是存在不可靠、无序等缺点。

基于TCP和UDP的优缺点,Google制定了一种基于UDP的低时延的互联网传输层协议—–即QUIC(Quick UDP Internet Connection)

在看了多个互联网产品的(微博、网易云信等)QUIC 加速服务架构与实践文档后,决定对现有的测试环境服务做QUIC改造并现场进行测试。

现有的开源实现:
1、quiche:这个是用 Rust 做的库,通过nginx调用。【不是Google的quiche库】
2、ATS:Apache Traffic Server
3、golang:Caddy;
4、python+C,aioquic
5、微软msquic

考虑到通用性和性能,我们最终选择了基于go的Caddy server进行测试。

因为caddy的v1版本和v2版本的配置是不相通的,所以往上很多文章都是已经过时的,我们看看官网怎么说:

For example, to configure different options for the servers on port :80 and :443, you would specify two servers blocks:[原文链接]

{
servers :443 {
protocol {
experimental_http3
}
}

servers :80 {
protocol {
allow_h2c
}
}
}

上述servers :443代码块就是实现HTTP/3(HTTP Over QUIC)的配置方式,示例中也提到了以明文方式传输HTTP/2(即H2C –”Cleartext HTTP/2” or “H2 over TCP”)的开启方式。

官网对这两个代码块也是有详细说明的:

allow_h2c:enables H2C (“Cleartext HTTP/2” or “H2 over TCP”) support, which will serve HTTP/2 over plaintext TCP connections if a client support it. Because this is not implemented by the Go standard library, using H2C is incompatible with most of the other options for this server. Do not enable this only to achieve maximum client compatibility. In practice, very few clients implement H2C, and even fewer require it. This setting applies only to unencrypted HTTP listeners. ⚠️ Experimental feature; subject to change or removal.(大概意思就是H2C实际上不会有人去用,此功能只是个实验性的功能,未来可能会更改或者删除。)

experimental_http3:enables experimental draft HTTP/3 support. Note that HTTP/3 is not a finished spec and client support is extremely limited. This option will go away in the future. This option is not subject to compatibility promises.(大概意思是HTTP/3不是完整的规范,客户端支持也有限。此选项未来会消失。也不受到兼容性承诺的约束。)

我们在测试中只需要在servers块下创建protocol块,然后指定experimental_http3即可。
即:

{
servers :443 {
protocol {
experimental_http3
}
}
}

注意⚠️ caddy的配置文件是按行区分的,是不带句尾分号的 ;

在实现HTTP/3之后,我们使用多种设备和运营商卡进行了多次现场测试。原本在现场遇到弱网情况下需要7s左右才能Finish的页面现在仅仅需要2s。极大的提升了加载速度!

得到测试结论后,我们要做的就是线上生产环境的改造。这时一个新的问题摆在我们面前:腾讯云CDN不支持HTTP/3。

这里我们进行了讨论得出两种方案:
1、自建一个小型的CDN网络供这个服务使用。
2、使用支持HTTP/3的CDN厂家。

第一个成本就比较高了,维护起来也比较麻烦。所以我们就选择了第二个方案,把这个服务接入到了支持HTTP/3协议的CDN厂家。这里就不做推荐了,大家要善用搜索引擎。