1、网络基础与性能指标:HTTP/HTTPS协议回顾、DNS解析原理、TCP三次握手与四次挥手、网络延迟的构成、关键性能指标(TTFB、RTT、吞吐量)
各位同学,咱们今天聊点最基础,但也最容易被忽视的东西——网络基础。
说实话,我见过太多Android开发同学,一上来就怼OkHttp、Retrofit,各种封装库用得飞起。但一问到「为什么你的接口有时候快有时候慢?」「TTFB到底代表什么?」就卡壳了。
嗯,这其实很正常。网络这东西,看不见摸不着,出了问题全靠猜。但作为架构师,你不能只靠猜。你得知道每一毫秒都花在了哪里。
1.1 HTTP/HTTPS协议回顾
先说说HTTP。HTTP是应用层协议,说白了就是客户端和服务器之间约定好的「对话格式」。你发一个请求,它回一个响应,就这么简单。
我个人习惯把HTTP协议分成两个维度来看:版本演进和安全机制。
HTTP/1.1 vs HTTP/2 vs HTTP/3
| 特性 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 连接复用 | 串行(需Keep-Alive) | 多路复用 | 多路复用(基于QUIC) |
| 队头阻塞 | 有 | 有(TCP层) | 无 |
| 传输层 | TCP | TCP | QUIC(基于UDP) |
| 握手次数 | 2-3次 | 1次(TLS复用) | 0-RTT |
我在项目中遇到过一个问题:某个页面同时加载20张小图,用HTTP/1.1时浏览器最多开6个连接,剩下的全排队。结果页面加载慢得像蜗牛。后来切到HTTP/2,多路复用直接解决了这个问题。
HTTPS的额外开销
HTTPS比HTTP多了TLS握手。你想想看,本来TCP三次握手已经够慢了,再加一次TLS握手,延迟直接翻倍。
不过别怕,现在有TLS 1.3,握手从2-RTT降到了1-RTT。还有Session Resumption,可以做到0-RTT。嗯,这里要注意:0-RTT有重放攻击风险,别用在幂等性要求高的接口上。
1.2 DNS解析原理
DNS解析,说白了就是把域名翻译成IP地址。你输入www.baidu.com,系统得先知道它的IP是多少,才能建立连接。
这个过程其实挺慢的。我测过,一次完整的DNS解析,平均耗时在50-200ms之间。如果DNS服务器在国外,甚至能到1秒以上。
DNS解析的完整链路是这样的:
- 浏览器缓存:先查本地有没有缓存过这个域名
- 系统缓存:没命中,查操作系统缓存
- 路由器缓存:还没命中,查路由器缓存
- ISP DNS服务器:再没命中,查运营商DNS
- 根域名服务器:最后才去根服务器递归查询
OkHttp的Dns接口自定义DNS解析,二是预解析常用域名。效果立竿见影。
1.3 TCP三次握手与四次挥手
TCP三次握手,每个Android开发都应该烂熟于心。但我发现很多人只是背了「SYN、SYN-ACK、ACK」这三个词,根本不知道它跟性能有什么关系。
来,咱们重新捋一遍:
- 第一次握手:客户端发SYN包,告诉服务器「我要连你」
- 第二次握手:服务器回SYN-ACK包,说「收到,我也准备好了」
- 第三次握手:客户端发ACK包,说「好,开始传数据吧」
三次握手需要1.5个RTT(往返时间)。如果你的RTT是100ms,那光握手就花了150ms。这还没算上后面的TLS握手呢。
四次挥手呢?
- 第一次挥手:客户端发FIN,说「我发完了」
- 第二次挥手:服务器回ACK,说「知道了,但我还有数据要发」
- 第三次挥手:服务器发FIN,说「我也发完了」
- 第四次挥手:客户端回ACK,说「收到,拜拜」
1.4 网络延迟的构成
网络延迟不是单一因素造成的。我习惯把它拆成四个部分:
| 延迟类型 | 典型耗时 | 优化方向 |
|---|---|---|
| DNS解析 | 50-200ms | 预解析、缓存、HTTPDNS |
| TCP握手 | 1.5 RTT | 连接池、HTTP/2多路复用 |
| TLS握手 | 1-2 RTT | TLS 1.3、Session Resumption |
| 数据传输 | 取决于带宽和文件大小 | 压缩、分片、CDN |
你想想看,一个请求从发出到收到响应,中间经历了多少环节?每个环节都可能成为瓶颈。
我记得有一次,一个同事跑来跟我说:「我接口响应时间500ms,但服务器日志显示只处理了50ms,剩下的450ms去哪了?」
我让他抓了个包一看,好家伙,DNS解析花了120ms,TCP握手花了150ms,TLS握手又花了100ms,真正传输数据才80ms。这就是典型的「网络开销远大于业务处理」。
1.5 关键性能指标
做性能优化,你得先知道「怎么衡量」。没有指标,优化就是瞎搞。
TTFB(Time To First Byte)
TTFB是从客户端发出请求,到收到服务器返回的第一个字节的时间。它包含了DNS解析、TCP握手、TLS握手、以及服务器处理时间。
我个人习惯把TTFB控制在200ms以内。超过500ms,用户就能明显感觉到「卡」了。
RTT(Round Trip Time)
RTT是数据包从客户端到服务器再返回的时间。它主要受物理距离和网络质量影响。
举个例子:你在北京访问上海服务器,RTT大概30ms。访问美国服务器,RTT可能200ms+。这就是为什么很多App要做「就近接入」——把服务器部署在离用户近的地方。
吞吐量(Throughput)
吞吐量是单位时间内传输的数据量。它跟带宽有关,但不等同于带宽。
我遇到过一个问题:明明带宽是100Mbps,但实际下载速度只有2MB/s。查了半天,发现是TCP窗口太小,导致带宽利用率极低。调整了TCP缓冲区大小后,速度直接翻倍。
NetworkStatsManager来监控应用的网络流量。但注意,这个API需要PACKAGE_USAGE_STATS权限,而且不同厂商的ROM实现有差异。
好了,这一章的内容就到这里。网络基础是性能优化的地基,地基不稳,上层建筑再漂亮也没用。下一章,咱们聊聊「Android网络请求框架选型与对比」——OkHttp、Retrofit、Volley到底怎么选?
公众号:蓝海资料掘金营,微信deep3321