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,多路复用直接解决了这个问题。

重点:Android端如果API Level >= 28(Android 9),默认就支持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解析的完整链路是这样的:

  1. 浏览器缓存:先查本地有没有缓存过这个域名
  2. 系统缓存:没命中,查操作系统缓存
  3. 路由器缓存:还没命中,查路由器缓存
  4. ISP DNS服务器:再没命中,查运营商DNS
  5. 根域名服务器:最后才去根服务器递归查询
避坑指南:我曾经在项目里遇到一个诡异问题——用户反馈某个接口偶尔超时。查了半天,发现是DNS解析不稳定。后来我们做了两件事:一是用OkHttpDns接口自定义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,说「收到,拜拜」
注意:四次挥手后,客户端会进入TIME_WAIT状态,持续2MSL(约2分钟)。如果频繁创建和关闭连接,会导致大量端口被占用。这就是为什么我建议你用连接池——复用连接,避免频繁握手和挥手。

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,用户就能明显感觉到「卡」了。

经验值:TTFB < 200ms(优秀),200-500ms(良好),> 500ms(需要优化)。

RTT(Round Trip Time)

RTT是数据包从客户端到服务器再返回的时间。它主要受物理距离和网络质量影响。

举个例子:你在北京访问上海服务器,RTT大概30ms。访问美国服务器,RTT可能200ms+。这就是为什么很多App要做「就近接入」——把服务器部署在离用户近的地方。

吞吐量(Throughput)

吞吐量是单位时间内传输的数据量。它跟带宽有关,但不等同于带宽。

我遇到过一个问题:明明带宽是100Mbps,但实际下载速度只有2MB/s。查了半天,发现是TCP窗口太小,导致带宽利用率极低。调整了TCP缓冲区大小后,速度直接翻倍。

小技巧:在Android端,你可以用NetworkStatsManager来监控应用的网络流量。但注意,这个API需要PACKAGE_USAGE_STATS权限,而且不同厂商的ROM实现有差异。

好了,这一章的内容就到这里。网络基础是性能优化的地基,地基不稳,上层建筑再漂亮也没用。下一章,咱们聊聊「Android网络请求框架选型与对比」——OkHttp、Retrofit、Volley到底怎么选?


公众号:蓝海资料掘金营,微信deep3321