网络零散
为什么分层
因为复杂,所以分层,每层各司其职。如现在的分布式微服务类似,复杂的系统就要分而治之。
nagle算法与cork算法
都是为了解决发送小数据包的开销问题,不同的是nagle是进行时间限制,而cork是进行大小限制:
- nagle
- 若数据包大于MSS可直接发送,否则需要接收到所有已发送报文的ACK才能继续发送下一个
- cork
- 把小数据包拼接成一个大的数据包(MSS)才能发送,当然,若超过一定时间还没满足则直接发送
参考链接:https://www.zhuxiaodong.net/2018/tcp-nagle-tcp_nodelay-tcp_nopush-instruction/
ip与MAC
局域网内用MAC(不太准确,如路由器之间的链路层寻址也是MAC),出了局域网用ip。
两大问题:
- 为什么有了ip还要有MAC?历史遗留问题,MAC先出现
- 为什么有了MAC还要有ip?MAC无法聚合,将会导致路由表巨大
在网络中传输时,网络层中IP的源地址和目的地址是不变的,但经过局域网的NAT转换例外,会修改源IP(向外发送时)或目的IP(向内发送时);而数据链路层中的MAC地址则会在每一跳中改变(源地址和目的地址都会变)
在任何一台机器上,当要访问另一个 IP 地址的时候,都会先判断,这个目标 IP 地址,和当前机器的 IP 地址,是否在同一个网段。若在同一网段,则MAC地址填入对方MAC(不知道则自己发送ARP),否则不在同一网段的话,MAC地址就填入网关MAC。
路由器不等于网关,如若一个路由器有5个网口,每个网口都是一个局域网,则每个网卡都是一个网关,那么一个路由器有5个网关,即路由器是设备,网关是接口
VLSM & CIDR
由于基于传统五类ip地址的划分导致ip资源浪费,vlsm出现是为了细化网络地址划分的颗粒度,但同时带来的是路由器中路由表项的急剧增加,降低网络性能,这时候引入cidr是为了降低路由器中路由表的大小,聚合路由,提升网络效率
B类网络地址由66634主机,而C类只有254个,一般公司C类少了,B类又浪费,所以出现了VLSM,但划分后路由项变多,所以CIDR又出现了
子网掩码代表着VLSM或CIDR中的掩码
- 可边长子网掩码:VLSM就是通过子网掩码向右移动,把网段拆分,划分子网
- 无类别域间路由:CIDR就是通过子网掩码向左移动,把网段汇聚在一起,以便减小路由表条目,简便管理
DHCP & ICMP
DHCP
工作在UDP之上的应用层协议

ICMP
封装在IP包内进行发送,类型分为两类:询问和差错,各类的类型值如下:
- 询问
- 类型值为8或者0时:表示回送(Echo)请求或应答
- 类型值为13或14时:表示时间戳(Timestamp)请求或应答
- 差错
- 类型值为3时:表示终点不可达(端口错误等问题)
- 类型值为11时:表示超时(TTL等问题)
ping使用icmp的询问报文,而tracert(windows)使用icmp询问报文进行询问,对方回应差错报文;但Linux上的traceroute使用udp,若超时或终点不可达则对方回应差错报文。所以tracert是主动使用ICMP,而traceroute是被动
Traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU。要做的工作首先是发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口 MTU 相等。如果中间遇到窄的关口会被卡住,会发送ICMP网络差错包,类型为“需要进行分片但设置了不分片位”,每次收到ICMP“不能分片”差错时就减小分组的长度,直到到达目标主机
TCP & UDP
TCP是连接的面向字节流的可靠传输,UDP是无连接面向数据报的非可靠传输
UDP
本质是加了端口的IP数据包 UDP占用资源小、简单、处理速度快。适合在通信条件好(如内网)或对于丢包不敏感的场合使用。如DHCP就是基于UDP的,一个是它在内网工作,第二个就是可容忍丢包,丢了再发就是,只不过延时一段时间获取IP,第三它是对外广播的,UDP占用资源小
TCP
从包结构来说,相对于UDP,TCP可靠的保障为其具有序列号(SEQ+ACK)和窗口大小,为其可靠传输技术如确认机制、重传机制和拥塞避免机制等提供基础
TCP三次握手的目的是同步连接双方的序列号和确认号并交换TCP窗口大小信息
丢包问题:
- 发送方未收到确认ACK:超时重传(每一个发送包都有一个定时器,时间为加权平均RTT)
- 发送方收到三个冗余ACK:快重传(不用等待超时)
- 当采用SACK时,重复ACK通常也包含SACK信息
- 接收方进行选择性确认:SACK
- SACK只是针对失序到达的报文段的,如果收到的报文段与期望收到的报文段的序号相同就会发送累积的ACK
快重传和SACK都是针对失序报文的
**流量控制:**滑动窗口
糊涂窗口综合征:窗口变小,每次发送极小报文,浪费带宽。
解决:nagle算法和clark算法
- nagle:针对发送端
- clark:针对接收端
- 只要有数据到达就发送确认,但宣布的窗口大小为零,直到或者缓存空间已能放入具有最大长度的报文段,或者缓存空间的一半已经空了。
**拥塞控制:**拥塞窗口
慢启动、拥塞避免、快重传、快恢复
BBR:
BBR通过实时计算带宽和最小RTT来决定发送速率pacing rate和窗口大小cwnd。完全摒弃丢包作为拥塞控制的直接反馈因素。
TCP的拥塞避免算法最终会填满通信链路上设备的缓存,使用缓存导致延时增加
- 设备缓存为什么会导致延时?
- 假如经过设备的包都不需要进入缓存,那么得到的速度是最快的。进入缓存且等待,等待的时间就是额外的延时。
- BBR如何解决延时?
- S1:慢启动开始时,以前期的延迟时间为延迟最小值Tmin。然后监控延迟值是否达到Tmin的n倍,达到这个阀值后,判断带宽已经消耗尽且使用了一定的缓存,进入排空阶段。
- S2:指数降低发送速率,直至延迟不再降低。这个过程的原理同S1
- S3:协议进入稳定运行状态。交替探测带宽和延迟,且大多数时间下都处于带宽探测阶段
应用协议
流媒体协议
客户直播端(推流到服务器)->服务器(从客户端接流)->客户观看端(从服务器拉流)

视频帧:
- I 帧,也称关键帧。里面是完整的图片,只需要本帧数据,就可以完成解码。
- P 帧,前向预测编码帧。P 帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面,叠加上和本帧定义的差别,生成最终画面。
- B 帧,双向预测内插编码帧。B 帧记录的是本帧与前后帧的差别。要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的数据与本帧数据的叠加,取得最终的画面。
一个视频,可以拆分成一系列的帧,每一帧拆分成一系列的片,每一片都放在一个NALU(网络提取层单元Network Abstraction Layer Unit)里面,NALU之间都是通过特殊的起始标识符分隔,在每一个I帧的第一片前面,要插入单独保存SPS和PPS的NALU,最终形成一个长长的NALU序列。
RTMP实时消息协议(Real-Time Messaging Protocol)、HLS(苹果端)
P2P协议
文件传输:HTTP、FTP(主动模式、被动模式(常用))、P2P
P2P:缓解了单一服务器的带宽压力
下载流程:
- 下载时,BT客户端首先解析.torrent文件,得到tracker地址,然后连接tracker服务器。tracker服务器回应下载者的请求,将其他下载者(包括发布者)的 IP 提供给下载者。
- 下载者再连接其他下载者,根据.torrent 文件,两者分别对方告知自己已经有的块,然后交换对方没有的数据。此时不需要其他服务器参与,并分散了单个线路上的数据流量,因此减轻了服务器的负担。下载者每得到一个块,需要算出下载块的 Hash 验证码,并与.torrent文件中的对比。如果一样,则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容的准确性问题。
- 从这个过程也可以看出,这种方式特别依赖 tracker。tracker需要收集下载者信息的服务器,并将此信息提供给其他下载者,使下载者们相互连接起来,传输数据。虽然下载的过程是非中心化的,但是加入这个 P2P 网络的时候,都需要借助 tracker 中心服务器,这个服务器是用来登记有哪些用户在请求哪些资源。
- 所以,这种工作方式有一个弊端,一旦tracker服务器出现故障或者线路遭到屏蔽,BT工具就无法正常工作了。
去中心化网络(DHT): Distributed Hash Table
每个加入这个 DHT 网络的人,都要负责存储这个网络里的资源信息和其他成员的联系信息,相当于所有人一起构成了一个庞大的分布式存储数据库。
一种著名的 DHT 协议,叫 Kademlia 协议
DNS
是分布式的高并发服务器
功能:域名解析、负载均衡
域名解析

负载均衡
- 内部负载均衡
一个域名多个IP,每次解析返回不同的IP - 全局负载均衡
CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。
httpDNS
HTTPDNS使用HTTP与DNS服务器交互,代替传统的基于UDP的DNS协议,域名解析请求直接发送到HTTPDNS服务端,从而绕过运营商的Local DNS
传统的 DNS 有很多问题,例如解析慢、更新不及时。因为缓存、转发、NAT 问题导致客户端误会自己所在的位置和运营商,从而影响流量的调度。
HttpDNS 通过客户端 SDK 和服务端,通过 HTTP 直接调用解析 DNS 的方式,绕过了传统 DNS 的这些缺点,实现了智能的调度。
- 防止域名劫持
- 由于 HttpDns 是通过 IP 直接请求 HTTP 获取服务器 A 记录地址,不存在向本地运营商询问 domain 解析过程,所以从根本避免了劫持问题。
- 精准调度
- HTTPDNS能够直接获取到用户的IP地址,从而实现精确定位与导流
CDN(内容分发网络)
CDN分发系统的架构:

从下向上请求,若连中心节点都没有缓存,则向源请求
客户端如何找到相应的边缘节点进行访问呢?通过基于DNS的全局负载均衡策略
有无CDN时的域名查询:
- 无CDN时
- 用户向浏览器输入 www.web.com 这个域名,客户端访问本地 DNS 服务器的时候,如果本地 DNS 服务器有缓存,则返回网站的地址;如果没有,递归查询到网站的权威 DNS 服务器,这个权威 DNS 服务器是负责 web.com 的,它会返回网站的 IP 地址。本地 DNS 服务器缓存下 IP 地址,将 IP 地址返回,然后客户端直接访问这个 IP 地址,就访问到了这个网站。
- 有CDN时,如下图
- 在 web.com 这个权威 DNS 服务器上,会设置一个 CNAME 别名,指向另外一个域名 www.web.cdn.com,返回给本地 DNS 服务器。
- 当本地 DNS 服务器拿到这个新的域名时,需要继续解析这个新的域名。这个时候,再访问的就不是 web.com 的权威 DNS 服务器了,而是 web.cdn.com 的权威 DNS 服务器,这是 CDN 自己的权威 DNS 服务器。在这个服务器上,还是会设置一个 CNAME,指向另外一个域名,也即 CDN 网络的全局负载均衡器。
- 接下来,本地 DNS 服务器去请求 CDN 的全局负载均衡器解析域名,全局负载均衡器会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:
- 根据用户 IP 地址,判断哪一台服务器距用户最近;
- 用户所处的运营商;
- 根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需的内容;
- 查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。

- CDN加速静态资源:
- 对于静态页面来讲,内容的分发往往采取拉取的方式,也即当发现未命中的时候,再去上一级进行拉取。但是,流媒体数据量大,如果出现回源,压力会比较大,所以往往采取主动推送的模式,将热点数据主动推送到边缘节点。
- 对于流媒体CDN来讲,有个关键的问题是防盗链问题。最常用也最简单的解决方法就是 HTTP 头的 referer 字段, 当浏览器发送请求的时候,一般会带上 referer,告诉服务器是从哪个页面链接过来的,服务器基于此可以获得一些信息用于处理。如果 refer 信息不是来自本站,就阻止访问或者跳到其它链接。但referer的机制相对比较容易破解,所以还需要配合其他的机制。一种常用的机制是时间戳防盗链。使用 CDN 的管理员可以在配置界面上,和 CDN 厂商约定一个加密字符串。
- CDN加速动态资源:
- 边缘计算的模式:既然数据是动态生成的,所以数据的逻辑计算和存储,也相应的放在边缘的节点
- 路径优化的模式:类似专线
CDN加速是对网站所在服务器加速,还是对其域名加速?
CDN是只对网站的某一个具体的域名加速。如果同一个网站有多个域名,则访客访问加入CDN的域名获得加速效果,访问未加入CDN的域名,或者直接访问IP地址,则无法获得CDN效果。
docker
虚拟机是操作系统级别的资源隔离,而容器本质上是进程级的资源隔离
环境隔离:用Linux namespace在内核级对环境进行隔离和虚拟化 https://coolshell.cn/articles/17010.html
资源限制:用cgroups对资源使用限制 https://tech.meituan.com/2015/03/31/cgroups.html
隧道
隧道协议(Tunneling Protocol)是一类网络协议,它是一种数据包封装技术,它是将原始MAC包或原始IP包(其报头包含原始发送者和最终目的地)封装在另一个数据包(称为封装的IP包)的数据净荷中进行传输。使用隧道的原因是在不兼容的网络上传输数据,或在不安全网络上提供一个安全路径
GRE协议封装的是IP包
IPSec协议封装IP包
VxLAN协议封装的是MAC包
VxLAN:除了VLAN的功能外,可通过网络隧道技术,使隧道两端的网络组合成一个更大的内部网络。方便虚拟机的动态迁移(虚拟机所在的物理机改变,但在此过程中IP不变)
因VxLAN协议封装的是MAC包,通过隧道连接后,相当于两端同属于一个链路层
RPC
- 封装:stub完成 序列化、编码、寻址
- 传输:RPCRuntime完成 网络数据传输
服务器架构
