目录

网络零散

为什么分层

因为复杂,所以分层,每层各司其职。如现在的分布式微服务类似,复杂的系统就要分而治之。

nagle算法与cork算法

都是为了解决发送小数据包的开销问题,不同的是nagle是进行时间限制,而cork是进行大小限制:

  1. nagle
    • 若数据包大于MSS可直接发送,否则需要接收到所有已发送报文的ACK才能继续发送下一个
  2. cork
    • 把小数据包拼接成一个大的数据包(MSS)才能发送,当然,若超过一定时间还没满足则直接发送

参考链接:https://www.zhuxiaodong.net/2018/tcp-nagle-tcp_nodelay-tcp_nopush-instruction/

ip与MAC

局域网内用MAC(不太准确,如路由器之间的链路层寻址也是MAC),出了局域网用ip。
两大问题:

  1. 为什么有了ip还要有MAC?历史遗留问题,MAC先出现
  2. 为什么有了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中的掩码

  1. 可边长子网掩码:VLSM就是通过子网掩码向右移动,把网段拆分,划分子网
  2. 无类别域间路由:CIDR就是通过子网掩码向左移动,把网段汇聚在一起,以便减小路由表条目,简便管理

DHCP & ICMP

DHCP

工作在UDP之上的应用层协议

/images/net/dhcp2.jpg

ICMP

封装在IP包内进行发送,类型分为两类:询问和差错,各类的类型值如下:

  1. 询问
    1. 类型值为8或者0时:表示回送(Echo)请求或应答
    2. 类型值为13或14时:表示时间戳(Timestamp)请求或应答
  2. 差错
    1. 类型值为3时:表示终点不可达(端口错误等问题)
    2. 类型值为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窗口大小信息

丢包问题:

  1. 发送方未收到确认ACK:超时重传(每一个发送包都有一个定时器,时间为加权平均RTT)
  2. 发送方收到三个冗余ACK:快重传(不用等待超时)
    1. 当采用SACK时,重复ACK通常也包含SACK信息
  3. 接收方进行选择性确认:SACK
    1. SACK只是针对失序到达的报文段的,如果收到的报文段与期望收到的报文段的序号相同就会发送累积的ACK

快重传和SACK都是针对失序报文的

**流量控制:**滑动窗口
糊涂窗口综合征:窗口变小,每次发送极小报文,浪费带宽。 解决:nagle算法和clark算法

  1. nagle:针对发送端
  2. clark:针对接收端
    1. 只要有数据到达就发送确认,但宣布的窗口大小为零,直到或者缓存空间已能放入具有最大长度的报文段,或者缓存空间的一半已经空了。

**拥塞控制:**拥塞窗口
慢启动、拥塞避免、快重传、快恢复

BBR:
BBR通过实时计算带宽和最小RTT来决定发送速率pacing rate和窗口大小cwnd。完全摒弃丢包作为拥塞控制的直接反馈因素。

TCP的拥塞避免算法最终会填满通信链路上设备的缓存,使用缓存导致延时增加

  1. 设备缓存为什么会导致延时?
    1. 假如经过设备的包都不需要进入缓存,那么得到的速度是最快的。进入缓存且等待,等待的时间就是额外的延时。
  2. BBR如何解决延时?
    1. S1:慢启动开始时,以前期的延迟时间为延迟最小值Tmin。然后监控延迟值是否达到Tmin的n倍,达到这个阀值后,判断带宽已经消耗尽且使用了一定的缓存,进入排空阶段。
    2. S2:指数降低发送速率,直至延迟不再降低。这个过程的原理同S1
    3. S3:协议进入稳定运行状态。交替探测带宽和延迟,且大多数时间下都处于带宽探测阶段

应用协议

流媒体协议

客户直播端(推流到服务器)->服务器(从客户端接流)->客户观看端(从服务器拉流)
/images/net/live.jpg

视频帧:

  1. I 帧,也称关键帧。里面是完整的图片,只需要本帧数据,就可以完成解码。
  2. P 帧,前向预测编码帧。P 帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面,叠加上和本帧定义的差别,生成最终画面。
  3. 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:缓解了单一服务器的带宽压力
下载流程:

  1. 下载时,BT客户端首先解析.torrent文件,得到tracker地址,然后连接tracker服务器。tracker服务器回应下载者的请求,将其他下载者(包括发布者)的 IP 提供给下载者。
  2. 下载者再连接其他下载者,根据.torrent 文件,两者分别对方告知自己已经有的块,然后交换对方没有的数据。此时不需要其他服务器参与,并分散了单个线路上的数据流量,因此减轻了服务器的负担。下载者每得到一个块,需要算出下载块的 Hash 验证码,并与.torrent文件中的对比。如果一样,则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容的准确性问题。
  3. 从这个过程也可以看出,这种方式特别依赖 tracker。tracker需要收集下载者信息的服务器,并将此信息提供给其他下载者,使下载者们相互连接起来,传输数据。虽然下载的过程是非中心化的,但是加入这个 P2P 网络的时候,都需要借助 tracker 中心服务器,这个服务器是用来登记有哪些用户在请求哪些资源。
  4. 所以,这种工作方式有一个弊端,一旦tracker服务器出现故障或者线路遭到屏蔽,BT工具就无法正常工作了。

去中心化网络(DHT): Distributed Hash Table
每个加入这个 DHT 网络的人,都要负责存储这个网络里的资源信息和其他成员的联系信息,相当于所有人一起构成了一个庞大的分布式存储数据库。

一种著名的 DHT 协议,叫 Kademlia 协议

DNS

是分布式的高并发服务器
功能:域名解析、负载均衡

域名解析

/images/net/dns.jpg

负载均衡

  1. 内部负载均衡
    一个域名多个IP,每次解析返回不同的IP
  2. 全局负载均衡
    CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。

httpDNS

HTTPDNS使用HTTP与DNS服务器交互,代替传统的基于UDP的DNS协议,域名解析请求直接发送到HTTPDNS服务端,从而绕过运营商的Local DNS

传统的 DNS 有很多问题,例如解析慢、更新不及时。因为缓存、转发、NAT 问题导致客户端误会自己所在的位置和运营商,从而影响流量的调度。
HttpDNS 通过客户端 SDK 和服务端,通过 HTTP 直接调用解析 DNS 的方式,绕过了传统 DNS 的这些缺点,实现了智能的调度。

  1. 防止域名劫持
    1. 由于 HttpDns 是通过 IP 直接请求 HTTP 获取服务器 A 记录地址,不存在向本地运营商询问 domain 解析过程,所以从根本避免了劫持问题。
  2. 精准调度
    1. HTTPDNS能够直接获取到用户的IP地址,从而实现精确定位与导流

CDN(内容分发网络)

CDN分发系统的架构:
/images/net/cdn.jpg

从下向上请求,若连中心节点都没有缓存,则向源请求
客户端如何找到相应的边缘节点进行访问呢?通过基于DNS的全局负载均衡策略

有无CDN时的域名查询:

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

/images/net/cdn2.jpg

  1. CDN加速静态资源:
    1. 对于静态页面来讲,内容的分发往往采取拉取的方式,也即当发现未命中的时候,再去上一级进行拉取。但是,流媒体数据量大,如果出现回源,压力会比较大,所以往往采取主动推送的模式,将热点数据主动推送到边缘节点。
    2. 对于流媒体CDN来讲,有个关键的问题是防盗链问题。最常用也最简单的解决方法就是 HTTP 头的 referer 字段, 当浏览器发送请求的时候,一般会带上 referer,告诉服务器是从哪个页面链接过来的,服务器基于此可以获得一些信息用于处理。如果 refer 信息不是来自本站,就阻止访问或者跳到其它链接。但referer的机制相对比较容易破解,所以还需要配合其他的机制。一种常用的机制是时间戳防盗链。使用 CDN 的管理员可以在配置界面上,和 CDN 厂商约定一个加密字符串。
  2. CDN加速动态资源:
    1. 边缘计算的模式:既然数据是动态生成的,所以数据的逻辑计算和存储,也相应的放在边缘的节点
    2. 路径优化的模式:类似专线

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

  1. 封装:stub完成 序列化、编码、寻址
  2. 传输:RPCRuntime完成 网络数据传输

服务器架构

/images/net/balance.jpg