新浪微博 聂永 - 《QUIC在手机微博中的应用实践》

HTTP协议虽没有限制只允许使用TCP传输,但一直以来都是依赖于TCP实现,这是事实标准。随着基于UDP之上构建的QUIC传输层协议的出现,其天生内嵌HTTP 2协议的支持,让我们在对外开放HTTP API时多了一种传输通道的选择。 微博移动产品部团队在将QUIC应用在移动端生产实践环境的实践过程中,通过在客户端和服务器端做出一些定制,比如QUIC直连、线上环境支持1-RTT和0-RTT握手优化机制等,逐渐摸索出适应自身的实际业务需求。在具体实践中,我们在QUIC规模部署中也踩了一些坑,定制开发了QUIC性能压测工具用于线上容量评估等,针对不同的实际场景我们的降级策略等等行为,在本次议题中,我们将完整的实践内容和反思,一一分享给大家。
展开查看详情

1.《QUIC在⼿手机微博中的应⽤用实践》 聂永 @ 微博产品部

2. ⽬目录 • ⼀一、起因 • ⼆二、服务器器端实践 • 三、客户端实践 • 四、反思

3.⼀一、起因

4. 1.1 出发点 • 让微博APP在初始连接时在⽹网络链路路层⾯面请求后端业务时能够再快⼀一点 • 在弱⽹网环境下尽可能的满⾜足⽤用户基本请求 • 在复杂多变的⽹网络环境下有更更多的链路路通道选择,增加后端业务的可⽤用性

5. 1.2 HTTPS 存在问题 • HTTPS (1.1 & 2.0) Over TCP with TLS • 完整握⼿手流程过⻓长(基于TLS 1.2) • ⾸首次连接 >= 3-RTT • 协议握⼿手缓存后 :2-RTT • 弱⽹网环境,TCP Head-of-Line blocking + TLS Record HOF = 双重阻塞 • ⽆无法实现真正多路路复⽤用 • TCP被嵌⼊入系统内核层,遗留留⽹网络设备僵化 • ……

6.1.3 QUIC,致⼒力力于成为下⼀一代的互联⽹网传输协议

7.1.4 QUIC,握⼿手流程缩短

8.1.5 QUIC,真正的多路路复⽤用

9. 1.6 QUIC其它特性 • 改进的、可选的拥塞控制机制 • Client:BBR,Server:Cubic • 前向冗余纠错 • 连接迁移 • ……

10.⼆二、服务端实践过程

11. 2.1 服务端技术选项 • go-quic • 不不活跃 • google quic server demo • 示范Demo存在 • 缺少线上⽣生产级特性⽀支持 • …… • Caddy + Quic • 提供⼀一站式⽹网络堆栈服务 • ⽐比较成熟 • 使⽤用者众多,更更新频繁

12.2.2 部署结构

13. 2.3 LVS DR针对UDP⽀支持不不够 • 场景:LVS DR模式 • TCP 泛监听,⽐比如:*:8080,LVS DR 运⾏行行正常 • 本机所有 IP上都有监听TCP 8080,外⽹网客户端正常收包&发包 • UDP泛监听,⽐比如:*:8443,LVS DR 表明上看运⾏行行正常 • UDP Server回包时,IP数据包中的Src源地址为内⽹网IP • 外⽹网客户端只能发包,但收不不到数据包

14.2.3.1 UDP在LVS-DR下需要显式绑定 • 假设VIP:8.8.8.8,内⽹网RS IP:10.10.10.10 • Caddy需要显式绑定:VIP:Port • eg:8.8.8.8:443 • 这样做就够了了吗 ?

15.2.3.2 LVS需要⼼心跳检测 • LVS健康检测判断RS实例例是否存活 • 需要绑定内⽹网IP:Port • Caddy已绑定VIP:Port,eg: 8.8.8.8:443 • 同⼀一个Caddy实例例没办法重复绑定 10.10.10.10:443 • 实际怎么操作 ?

16. 2.3.3 应对LVS⼼心跳检测 • ⽅方式不不⼀一⽽而⾜足 • ⽐比如可以借助于netcat • eg:ncat -u -l 10.10.10.10 443 -k -c 'echo “hello”' • 进阶:supervisor + ncat

17. 2.3.4 LVS-DR UDP端⼝口绑定⼩小结 • Caddy bind:VIP:Port (eg:8.8.8.8:443) • ncat bind:RS_IP:Port(eg:10.10.10.10:443)

18.2.4 nginx & caddy的协作

19.2.4.1 QUIC Discovery

20.2.4.2 Nginx & Caddy协作

21. 2.4.3 Nginx & Caddy端⼝口不不冲突 • Caddy监听 444 端⼝口,UDP:444,TCP:444 • Nginx监听TLS 443端⼝口: • add_header Alt-Svc 'quic=":444"; ma=2592000; v=“38,37,36"'; • OpenResty监听TLS 443端⼝口: • ngx.header["Alt-Svc"] = 'quic=":444"; ma=2592000; v=“38,37,36"'

22.2.4.4 Nginx + Caddy混跑都监听443端⼝口 • 实际情况:Nginx TCP 443 + Caddy UDP 443 • Caddy’s TCP替换成⼀一个⾮非常规端⼝口 • udpAddr, err := net.ResolveUDPAddr("udp", strings.Replace(s.Server.Addr, ":45678", ":443", 1)) • Caddy TCP 45678,UDP 443 • OpenResty • ngx.header["Alt-Svc"] = 'quic=":443"; ma=2592000; v=“38,37,36”’ • nginx • add_header Alt-Svc 'quic=":444"; ma=2592000; v=“38,37,36"';

23. 2.4.5 Nginx & Caddy⼩小结 • nginx负责HTTPS,caddy负责QUIC,共同协作 • 在都占⽤用443端⼝口情况下 • nginx & caddy不不建议混跑 • nginx & caddy 错开部署,LVS指向RS不不同 • 端⼝口不不冲突,可以选择混合或错开部署

24.2.5 QUIC握⼿手流程,现实和理理想差距

25.2.5.1 握⼿手优化 2-RTT -> 1-RTT

26.第⼀一次握⼿手时放宽条件限制

27. 2.5.2 握⼿手优化到此结束了了没? • 场景:在前⾯面优化基础上,针对再次连接⽤用户 • ⽹网络切换导致客户端缓存失效 • 同⼀一机房接⼊入服务实例例改变导致缓存失效

28.2.5.3 1-RTT -> 0-RTT

29. 2.5.4 0-RTT,全局级握⼿手缓存 • 针对再次连接⽤用户 • ⽤用户的第⼀一次连接后握⼿手信息保存 到MC中 • ⽤用户下次连接落到哪⼀一个机房都会 0-RTT握⼿手流程