老梗 - 浏览器按回车后发生了什么
想起了一个老问题:浏览器按下回车的时候,后续流程是怎么变化的。
这个问题非常精妙,基本上把网络问题一次打包了。
对相关知识面了解越多的人,能说的内容也越多。越资深的人,能说的时间也越长。
我对网络也一直感兴趣,索性这次就做了大图,越做就盘子越大耗时越多,每个点都可以延伸一个举足轻重的行业。
浏览器按下回车键后,发生了太多太多事情,我文字理下图中写不下的重点,详细看下面大图。大图下载地址
DNS
- 重点是时机。DNS 查询是为了域名和 IP 映射,所以它的时机非常非常靠前,是所有网络活动的第一步。
- 发挥大作用的是负载均衡。
- 误解最大的是根 DNS。有镜像 DNS 在,不要拿封锁大陆域名后会怎么怎么样来做文章,技术同学说这话是要丢人的。如果这么做,我能想到的最大影响就是:大陆主动拒绝外界网络,外界都不愿意打开大陆访问,其实都是自由的选择。
- httpDNS 可以解决 DNS 污染和劫持问题,还有运营商偷懒导致的跨网非最近节点不准确问题,加快域名和 ip 的映射。一般只用在移动端,技术方案是 hook gethostbyname api 这个环节。别想着请求前把域名换成 ip,坑很多,尤其是 TLS 证书验证的时候。
Socket 套接字
- 网络通信的基石,只要是网络通信,这就是绕不开的大山,这就是中流砥柱。
- socket 的核心在于 socket 描述符和发送接收缓冲区。发送接收缓冲区不是 socket 特有的,是计算机基础的一部分,我们使用终端的时候,输入指令和参数的时候都在使用这套缓冲区。
- 大名鼎鼎的三次握手就在 socket 建联的时候发生的。成也萧何败也萧何,因为 socket 是内嵌计算机的底层服务,也包括 TCP。所以即使三次握手已经拖慢了互联网这么多年,但依旧无法做升级。Quic 的出现就是忍不了 socket tcp 的队头阻塞而破釜沉舟的东西。
- socket tcp 的详细过程,可查阅之前文章:TCP 数据传输过程分析
- 谈 socket 离不开端口,谈端口离不开进程。可查阅之前文章:Shell 和进程 - 两种进程创建方式
- socket 本身可查阅之前文章:IM 和 Socket 的关系及 Heart 的必要性
用户网络
- 基站的圆形辐射覆盖范围有限,做火车的时候就是在频繁的更换基站。尤其偏远的地方,在火车周边每隔一段距离就有一个基站。基站应该是中国铺的最广的民用基建了,这也是运营商升级缓慢的原因,成本很大。
- 国内 sim 卡,在国外有的能上 twitter 有的不能上,是虚拟隧道的那一端到底在国内还是国外的原因。
- 疫情期间能知道哪些人经过了什么地方,就是因为基站的背后就是路由器和互联网,手机到哪就知道人到哪了。我疫情初期听过这么一个案例:一个人黄码了,然后他是内部工作人员,就去删了自己手机号的行程数据,黄码就立刻变绿码了。3 年过去了,现在健康码的操作权限还是很大,不仅可以手动删数据,还可以手动加数据,可以指定哪些人展示什么码。
七层五层网络协议
- 网络通信的基石,和 Socket 一样是中流砥柱。不过 socket 那一层需要复杂的编码,这一层只能躺着使用,可以窥看它的实现,有不爽的地方也无能为力。
- 会话层的 TLS 是 HTTP 和 HTTPS 的差异,这一块集中了密码学的知识。TLS 的耗时是非常可观的,要想躺着减小耗时,就尽快升级到 TLS1.3。其次,尽快用 ECDHE 代替 RSA,ECDHE 减小了签名大小、解密时间,还支持抢跑。
- 传输层的 TCP 详细过程,可查阅之前文章:TCP 数据传输过程分析
- 这里有两个重要的 case,就是 MTU 和 MSS。传输层的 MSS 会拆包,叫分段,IP 层的 MTU 也会拆包,叫分片。当包在网线传输的时候,其他的路由器属于三层设备,可以将包解到第三层即 IP 层,这个时候也就拿到了 MTU 范围内的全部包数据,如果包数据不符合当前路由器的 MTU 大小设置,可以将包抛弃,或者拆成更小的包后继续传给服务器,服务器会根据编号进行重组 (分片重组)。包里面可以设置一个参数,当路由器 MTU 过小需要拆包的时候,不允许拆包,强制直接丢弃。因为 IP 层面的拆包,是风险很大的,这个时候包里面没有了传输层的头部,有可能会服务器侧各种拦截。
- MAC 层会通过 ARP 拿到下一跳的路由器或者主机的 MAC 地址。MAC 地址并不是电脑本身的一部分,而是网卡的一部分。在电脑主机启动后,网卡驱动会对网卡进行初始化,这个时候网卡有一片 ROM 区域会被驱动配置。后续拿的 mac 地址,其实就是从网卡的这个 rom 区域拿的。
- UDP 和 TCP 的根本差异,不在于稳定性和使用方式,而在于包大小。如果每个包都很小,那么 UDP 要比 TCP 传输的更高效。只是有些包比较大,UDP 传输的话,一个包丢了就得全部重传。TCP 可以通过稳定的复杂机制来保障快速重传。比如 DNS 查询,就是通过 UDP 来发包的。DNS 查询很重要,为什么没有使用 TCP 的稳定通道?就是所有数据就一个包大小,丢了就丢了,没有回执就是丢了嘛,那就再重传一下。
NAT 路由
- 核心啊,能上网就靠它了。大图里面详细说了 NAT 的流程,包括 MAC 层 MAC 地址与 网络层 IP 地址的变化,以及 NAT 映射表和端到端隧道穿越的实现。
浏览器渲染
- 这里重点说了 V8 对 javascript 支持。详细可查阅之前文章:Shell 和进程 - 解释编译混合型语言
- 图片渲染部分,以及如何实现渐进式图片,可查阅之前文章:文件存储差异 - 编码
CDN 加速
- 和 DNS 一样,CDN 负载均衡服务器非常有用处。
- 要提高加速的命中率。即预推要及时,减少回流的概率。
- 缓存策略要控制好。可以通过 HTTP head 在客户端和服务端同时做缓存。