[实践—网络优化] 升级 HTTP2 协议

本文基于真实项目优化过程

奇怪的错误日志

在 firebase 统计的日志中发现出现频率最高的问题和 Http2 连接超时有关系,但是和服务端交谈得知他们并没有开启 Http2!那么这个问题怎么来的呢?是 Okhttp 内部错误问题还是我们使用不当导致的。

在这里插入图片描述

网络出了问题怎么办,答案只有一个:抓包!

使用 WireShark 抓包看到了如下内容:

  1. 在 Client Hello 的时候客户端在 ALPN 协议中声明了客户端支持的协议类型,

在这里插入图片描述

这符合 OkHttp 的默认配置

在这里插入图片描述

  1. 在 Server Hello 的时候服务端选择了使用 Http2 (h2) 协议进行传输。

在这里插入图片描述

通过 curl 命令也证明了后端支持 http2

$input> curl --http2 -v -H '隐去具体链接'

$output>
* Trying 13.232.215.xx...
* TCP_NODELAY set
* Connected to chatroom.funshareapp.com (13.232.215.xx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.xxxx.com
*  start date: Nov 22 00:00:00 2020 GMT
*  expire date: Dec 21 23:59:59 2021 GMT
*  subjectAltName: host "xxxx.xxxxx.com" matched cert's "*.xxxxx.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f8cb380c400)
> GET 隐去请求 HTTP/2
> Host: chatroom.funshareapp.com
> Accept: */*
> Accept-Encoding: deflate, gzip
> Authorization: 隐去
> User-Agent: okhttp/4.6.0
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< date: Wed, 14 Apr 2021 02:13:03 GMT
< content-type: application/json
< content-encoding: gzip
< server-cost: 125
< server-received-at: 2021-04-14 02:13:03.332024329 +0000 UTC
<

这也就是说明了后端的确有使用 Http2 协议,只不过他们不知情。

进一步交流得知,http2 是网关默认支持的,而服务端的 Http core 是自己实现的,要支持 Http 2 有点难度 现在明确了开头提到的 Http2 超时问题并不是子虚乌有的,它是个有因果关系的正常问题。

解决方案

初步尝试加大 Okhttp 的连接池数量,减小阻塞。扩大连接数量也和后端确认过,这个量级不会给服务器造成压力。

/**
 *
 * Create by im_dsd 2021/1/27 14:29
 */
class OkHttpClientFactoryWrapper(private val factory: OkHttpClientFactory) : OkHttpClientFactory {
    override fun create(): OkHttpClient {
        return factory.create()
                .newBuilder()
                .dns(DnsTrafficProxy(Dns.SYSTEM))
        		 // 连接数量扩大为原来的 2 倍,包活时间没有改变
                .connectionPool(ConnectionPool(10, 5, TimeUnit.MINUTES))
                .build()
    }
}

就 togo 项目的实际情况来看,截止至21年4月14日 app 内使用的域名多达14个(详情参见HttpProtocol),这说明了最大连接数设置为 10 也不过分。有些大厂会将最大连接数和域名数量保持一致,保证每个域名都有属于自己的 TCP 连接。但是我们的域名实属有点多,开太多的连接恐怕会弄的资源紧张,所以先开10个看看效果。

补课时间到

Http2 前一段时间特意学习了解过,但是真的到实战中,一被问到预计有什么提升瞬间感觉脑袋一片空白……

在这里插入图片描述

简单的说 Http/2 延时更低、速度更快.

HTTP/2: the Future of the Internet 这是 Akamai 公司建立的一个官方的演示,用以说明 HTTP/2 相比于之前的 HTTP/1.1 在性能上的大幅度提升。 同时请求 379 张图片,从 Load time 的对比可以看出 HTTP/2 在速度上的优势。

在这里插入图片描述

此时如果我们打开 Chrome Developer Tools 查看 Network 一栏可以发现 HTTP/2 在网络请求方面与 HTTP/1.x 的明显区别。

Http1.xHttp2
在这里插入图片描述在这里插入图片描述

为啥 Http/2 性能更好

Http2Http1.1
请求方式Http/2 是全双工、多路复用:一个 TCP 连接同时可以发起多个请求-响应,请求与响应均可并行。请求是串行的,就算是 pipline 将若干个请求排队串行处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞(Head of Line Blocking);
数据格式体积更小的二进制数据。首部信息会被封装到 HEADER frame,而相应的 Request Body 、Response Body则封装到 DATA frame 里面。每个数据帧都有自己的编号,传输顺序可完全乱序,接受方会按编号重组。
TCP 连接由于 TCP 连接的减少而使网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快TCP 慢启动起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。
头部处理对头部进行压缩对头部没有处理
Push服务端可以根据客户端的请求主动下客户端多次下发数据,较少了 RTT 时间不支持服务端 push ,例如一个网页所有的资源都得单独的去请求,RTT 时延高

在这里插入图片描述

结合 OkHttp

看链接池上的注释:连接池的数量对 HTTP 和 HTTP2 都有影响

/**
 * Manages reuse of HTTP and HTTP/2 connections for reduced network latency. HTTP requests that
 * share the same [Address] may share a [Connection]. This class implements the policy
 * of which connections to keep open for future use.
 *
 * @constructor Create a new connection pool with tuning parameters appropriate for a single-user
 * application. The tuning parameters in this pool are subject to change in future OkHttp releases.
 * Currently this pool holds up to 5 idle connections which will be evicted after 5 minutes of
 * inactivity.
 */
class ConnectionPool internal constructor( internal val delegate: RealConnectionPool) {

总结

  1. 实战很重要,看过100篇相关的技术文字都不如解决一个实际问题来的深刻。
  2. 根据项目需要学习,用力太猛的人跑不远。

参考

HTTP/2 相比 1.0 有哪些重大改进? - 知乎

Okhttp如何开启的Http2.0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值