物理层
通过比特流进行传输,这里略过。
数据链路层
使用以太网帧进行传输数据。
STP 协议(生成树协议),解决了交换机连接交换机之间的环路问题。由于交换机为了冗余、带宽提升、或者错误连接,难免会产生一个封闭的物理环路,而以太网的转发机制又决定了不能有物理环路,一有环路,那些发给所有主机的包如广播包,就会永远在环路上转圈,到达不了目的地,交换机的CPU飙升。
VLAN:全程虚拟局域网,由于二层交换机会转发所有的群发内容,可以划分多个虚拟局域网来避免广播内容的安全问题。 vlan 只需要在二层的头上加一个 TAG, 12 位,可划分 4096 个 VLAN。
网络层
如果网络发生了问题,可以使用以下命令进行排障:
查看 ping 包到了哪个设备开始返回的,直接定位可能故障的设备
tcpdump -i eth0 icmp
跟踪数据包通过的路线,使用 traceroute
,原理:发送一个 UDP 数据包,将 TTL 设置为 1、2、3… 利用 ICMP 规则,设置 TTL,比如第一个设置为 1 ,遇到第一个路由器后就挂了,对方就会返回一个 网络差错包即超时包。依次进行,这样就拿到了所有路由器 IP,当然有的路由器压根不会回复这个 ICMP。
traceroute 如何确定目标主机超时:traceroute 程序会发送一份 UDP 数据报给主机,但是会选择一个不可能的值作为 UDP 的端口号(大于30000),如果数据报没有到达,则可能是超时。
traceroute 探测 MTU:通过发送分组,并设置不分片标志。如果被卡了,就会收到 ICMP 的 网络差错包,类型为 “需要进行分片但设置了不分片位”,然后依次减小包的大小直接不会受到错误为止,就确定了某个设备的最大 MTU。
查看路由: ip route
或者 route
,在有多个网关的时候可以手动为指定客户端添加路由规则,如通过客户端IP地址限制某个客户端强制走某个网口:
1 |
|
以上代码设置了规则,从 192.168.1.101 来的包都查 test 这个新的路由表, 后面两条命令是在 test 路由表中添加具体路由规则。
三层算法: OSPF Wiki百科 (开放式最短路径优先),某些时候可以发现多个最短路径,可以在多个路径中进行负载均衡,这常常被称为等价路由。
基于距离矢量路由算法的 BGP Wiki 百科 全程边界网关协议。
传输层
UDP 和 TCP , 在某些实时传输中,使用 UDP,因为如果使用 TCP ,一旦遇到丢包,TCP 会启动拥塞控制,让原本网络就不好的环境,数据传输效率更低了。
UDP 可以保证低延迟。如果你要实现自己的应用需要有自己的链接策略,可靠保证,时延要求,使用 UDP,然后在应用层实现控制再好不过了。
网页或者 APP 访问, HTTP 协议基于 TCP,建立连接都需要多次交互,对于时延比较大的目前主流的移动互联网来讲,建立一次连接需要的时候会比较长,然而既然是移动中, TCP 可能还会断了重连,也很耗时的。而且目前的 HTTP 协议,往往采取多个数据通道共享一个连接的情况,这样本来为了加快传输速度,但是 TCP 的严格顺序策略使得哪怕共享通道,前一个不来,后一个和前一个即使没关系,也要等着,时延会加大。
而 QUIC (全程 Quick UDP Internet Connections, 快速 UDP 互联网连接)
是 Google 提出的一种基于 UDP 改进的通信协议,其目的是降低网络通信延迟,提供更好的用户互动体验。
QUIC 可以实现快速连接建立、减少重传时延,自适应拥塞控制。
流媒体协议使用的是 TCP 协议,对于直播行业,宁可丢包 也不要卡顿。
实时游戏中,维护 TCP 连接需要在内核维护一些数据结构,因而一台机器能够支撑的 TCP 连接数目是有限的,然而 UDP 是没有连接的, 在 异步 IO 机制引入之前,UDP 常常是应对海量客户端连接的策略。
TCP 的强顺序问题,对战游戏如果是 TCP ,若出现丢包,则会卡着不动,等回过神已经GG了。
IOT 物联网,嵌入式系统内存较小,维护 TCP 代价太大,另外物联网对实时性要求也很高,而 TCP 会由于种种原因增大延时。 Google 旗下的 NEst 建立 Thread Group, 推出了物联网通信协议 Thread,就是基于 UDP 协议的。
移动通信领域,面向协议 GTP-U 是基于 UDP 的。而 GTP 协议本身就包含复杂的手机上线下线的通信协议。如果基于 TCP,TCP 的机制就显得非常多余。
TCP:
seq 为什么不从 1 开始?
如果第一次发了 1,2,3 个包,第三个包每到,连接断了。重连后,重发了 1,2 但是没想发送3, 但是上一次的 3号包绕了一圈到了,导致了数据错乱,所以 seq 要随机。
建立连接后,seq 的确定是 32 为的计数器,每 4 ms 加一,如果要重复学院 4个多小时。IP包里有TTL,4个小时一定挂了。
2MSL: 等待时间设为 2MSL,报文最大生存时间, 它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为 TCP 报文基于是 IP 协议的, 而 IP 投中有一个 TTL 域, 是 IP 数据包可以经过的最大路由数,每经过一个处理它的路由器就减一,当此值为0则数据报被丢弃,同事发送 ICMP 报文通知源主机。协议规定 MSL 为 2分钟,实际应用中常用的是 30 秒、1分钟、2分钟等。
如果最后等待 2MSL 超时了,A会重新发送FIN的 ACK ,这个时候,B 有可能根本不认了,直接发送 RST 包,A 就知道B 已经早关闭了连接。
TCP 包头很复杂,主要关注5个问题: 顺序问题、丢包问题、连接维护、流量控制、拥塞控制
netstat -nat // 查看TCP各个链接状态的数量
流量控制: 滑动窗口
拥塞控制:避免包丢失和超时重传, 慢启动 开始指数增长,后面线性增长
拥塞的一种表现是丢包,需要超时重传。将 cwnd 设为 1 重新开始慢启动。这种方式太激进了,将一个告诉的传输速度一下子停了下来,会造成网络卡顿。
快速重传算法: 当接收端发现丢了一个中间包的时候,会发送三次前一个包的 ACK,于是发送端就会快速的重传,不必等待超时再重传。 TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,这样避免了一页回到解放前。
TCP 的拥塞控制主要来避免的两个现象都有问题
第一个问题:丢包并不代表着通道满了,也可能是管子本身就漏水。例如公网上带宽不满也会丢包,这个时候就认为拥塞了,退缩了是不对的。
第二个问题:TCP 的拥塞控制要等到将中间设备都填满了,才发生丢包,反而降低速度,这时候已经晚了。其实 TCP 只要填满管道就可以了,不应该接着填,知道缓存也填满。
为了优化这两个问题,后来有了 TCP BBR 拥塞算法。它企图找到一个平衡点,就是通过不断的加快发送速度,将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡点可以很好的达到高带宽和低时延的平衡。
应用层:
http协议: http1.1 再应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 头, 而且不考虑 pipleline 模式的话,每次的过程总是一去一回,这样在实时性,并发性上都存在问题。
为了解决这些问题, HTTP 2.0 会对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引。
另外, HTTP 2.0 协议将一个 TCP 的连接中,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。
HTTP2.0 还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。常见的帧有 Header 帧, 用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于一个流。
通过这两种机制, HTTP2.0 的客户端可以将多个请求分到不同的六中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打乱散序发送,然后根据每个帧首部的标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。
HTTP2.0 成功解决了 HTTP1.1 的队首阻塞问题,同时也不需要 HTTP1.x的 pipeline 机制用多条 TCP 连接来实现并行请求与响应;减少了 TCP 连接数对服务器性能的影响,同时将页面的多个数据 css、js、jpg 等通过一个数据链接进行传输,能够加快页面组件的传输速度。
HTTP2.0 本质上还是基于 TCP, 所以如果 TCP 丢包,也会造成重传和带宽的浪费。
QUIC:
- 自定义链接机制,通过 ID 标识,TCP 当IP或者端口发生变化的时候,就会重连, QUIC 只要 ID 不变就不会重连。
自定义重传机制:TCP通过自适应算法进行采样 RTT 不断调整,但是不准确,有可能发了一个1号包已超时,再次发送后,服务端并不知道 客户端 ACK 的是前一个1号包还是后一个,所以存在把时间算短了和算了长了。 QUIC,如 1号包丢了,它的下一个序号就是 2号包,而客户端通过 offset 偏移量进行确定 2 号包和 1 号包其实是同一个包,而不是通过序列号进行判断,这样 RTT 的计算时间相对准确。
物阻塞的多路复用,有了自定义的链接和重传机制,就可以解决 HTTP2.0 的多路复用问题。
- 自定义流量控制,和TCP 不同的是,QUIC ACK 是基于 offset 的,每个 offset 包来了,进入了缓存就会应答,应答后就不会重发,中间的空档会等待到来或者重发即可。窗口的起始位置为当前收到的最大的 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。显然这样更加精确,也不需要考虑缓存中确认了,最后由于缓存满了丢包问题。
总结: HTTP2.0 通过 头部压缩、分帧、二进制编码、多路复用等技术提升性能。QUIC 协议通过基于 UDP 自定义的类似 TCP 的连接、重试、复用、流量控制技术,进一步提升性能。