探索计算机网络|青训营笔记

109 阅读12分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第6篇笔记

  • 路由是工作在哪一层协议

    • 可以回答 IP 层,但是实际上可能有多层,例如需要使用到如 BGP、OSPF协议,此时应该是应用层
  • 路由不一定对称,因为可以有多条路线走

  • 路由不会改 IP 地址,如果需要前往路由器,那么此时首先会使用 ARP 协议请求路由器的 MAC 地址,然后修改 MAC 地址将报文转发到相应的路由器

  • ARP 协议:

    • ARP 请求是广播,ARP 应答是单播
    • 逻辑同网段才能发送 ARP
    • 免费 ARP:向全网广播地址更新表单、当服务器新增 IP 地址也会发送 ARP(避免 IP 冲突)
    • ARP 代理:中介作用,劫持一个 ARP 请求抢先应答
    • 本质用于查找 MAC 地址
  • 为什么不直接使用 MAC 地址

    • MAC地址用来唯一地标识一个网络接口,但它没有寻址功能。不同的网络使用不同的硬件地址,要使这些网络能够互相通信,就必须进行非常复杂的硬件地址转化工作,由用户或用户主机来完成这项工作几乎是不可能的事。IP编址就就是来解决这个问题的,连接到互联网的主机只需要各自拥有一个IP地址,它们之间的通信就像连接在同一个网络那么简单方便。
  • 有了 IP 为什么还要使用 MAC 地址

    • 并非每个主机都一个公网IP,很多主机都是使用的内网 IP,依据 NAT 对外访问。IP 地址是动态变化的,所以需要利用MAC地址来确定目标主机
  • IPv4 不够用解决方法

    • 使用 NAT(网络地址转换),改变套接字(IP + 端口号)
  • DNS

    • 域名到IP地址的解析是由分布在互联网上的许多域名服务器程序共同完成的
    • 解析过程:
      1. 应用程序需要把主机名解析为IP地址,调用解析程序,并成为DNS的一个客户
      2. 将带解析的域名放在DNS的请求报文中,以UDP用户数据报方式发给本地域名服务器
      3. 本地域名服务器查找域名后,把对应的IP地址放在回答报文中返回
      4. 应用进程获得目的主机的IP地址后即可进行通信
    • 域名的解析过程:
      • 主机像本地域名服务器的查询一般采用递归查询
      • 如果主机所询问的本地域名服务器不知道被查询域名的IP地址,那么本地域名服务器就以DNS客户的身份向其他域名服务器发出查询请求,而不是让主机自己进行下一步查询
      • 本地域名服务器向根域名服务器的查询通常采用迭代查询
        • 当根域名收到查询请求报文时,要么给出地址,要么让本地域名服务器进行后续的查询,不断迭代直到找到或者报错
  • UDP 用好很难:

    • 需要避免分片,因此需要计算每次发包
    • 怎么知道没有丢包
    • 怎么权衡传输效率和质量
  • TCP 连接:

    • 如果拔掉网线,需要取决于是否有保活(keep-alive)

    • 三次握手:

      • TCP建立连接的过程叫做握手,需要在客户和服务器之间交换三个TCP报文段,也称为三报文握手
      • A 的 TCP 向 B 发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x
        • 注意:SYN=1 请求报文段不能携带数据,但是要消耗掉一个序号
      • B 的 TCP 收到连接请求报文段后,如同意,则发回确认,在确认报文段中应使SYN = 1,使ACK = 1,其确认号ack = x + 1,自己选择的序号 seq = y
      • A 收到此报文段后向 B 给出确认,其 ACK = 1,确认号 ack = y + 1,A 的 TCP 通知上层应用进程,连接已经建立,进入ESTABLISHED状态
        • 注意:ACK报文段可以携带数据,但如果不携带数据则不消耗序号,如果不消耗则下一个序号seq 依旧为x+1
      • B 的 TCP 收到主机 A 的确认后,也通知其上层应用进程:TCP 连接已经建立,进入ESTABLISHED状态
      • 在TCP连接建立过程中,发送方A还要发送一次确认的原因:为了防止已经失效的连接请求报文段突然又传送到B
    • 避免分片:

      • 最大报文段长度MSS:每一个TCP报文段中的数据字段的最大长度,数据字段加上TCP首部才是整个TCP报文段
        • 与接收窗口无关
        • 为提高网络传输效率考虑,MSS 应尽可能的大,只要在 IP 层传输时不需要再分片就行
        • 两个传送方向可以有不同的 MSS 值,若没有填写的话则默认为 536 字节(576 字节的 IP 数据报的总长度减去 TCP 和 IP 的固定首部),因此所有互联网上的主机都应能接受的报文段长度是 536+20(固定首部长度)=556字节
        • 在三次报文段握手的时候,会最终取双方的最小值作为协商
      • 时间戳:
        • 10字节,最主要的字段是时间戳值字段(4字节)和时间戳回送回答字段(4字节)
        • 用来计算往返时间RTT
        • 用于处理TCP序号超过 2322^{32} 的情况,又称为防止序号绕回 PAWS,为了使接收方能够把新的报文段和迟到很久的报文段区分开
    • Timewait:

      • 避免 TCP 报文段丢失,保证连接的正常关闭
      • 不能设置得太长了避免占用端口
    • 丢包重传需要依据 ACK

    • 拥塞控制的算法:

      • 慢开始
      • 拥塞避免
      • 快重传
      • 快恢复
    • 基于窗口的拥塞控制

      • 拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化

        • 发送方让自己的发送窗口等于拥塞窗口
        • 考虑到接收方的接收能力,则发送窗口还可能小于拥塞窗口
      • 原则:

        • 只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去
        • 但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数
      • 只要发送方没有按时收到应当到达的确认报文时,即出现了超时,就可以估计可能在网络某处出现了拥塞,即发送方在超时重传计时器启动时,就判断网络出现了拥塞

      • “加法增大”:执行拥塞避免算法后,在收到对所有报文段的确认后(即经过一个往返时间),就把拥塞窗口 cwnd增加一个 SMSS 大小,使拥塞窗口缓慢增大,以防止网络过早出现拥塞

      • “乘法减小”:不论在慢开始阶段还是拥塞避免阶段,只要出现一次超时(即出现一次网络拥塞)或者3个重复的确认,就把慢开始门限值 ssthresh 设置为当前的拥塞窗口值的一半,并大大减小拥塞窗口的数值

      • 发送端的发送窗口不能超过拥塞窗口 cwnd 和接收端窗口 rwnd 中的最小值

        • 发送方窗口的上限值=Min[rwnd,cwnd]发送方窗口的上限值 = Min[rwnd,cwnd]
        • 当 rwnd<cwnd 时,是接收方的接受能力限制发送方窗口的最大值

        • 反之,当 cwnd<rwnd ,则是网络的拥塞程度限制发送方窗口的最大值

        • 也就是说, rwnd 和 cwnd 中数值较小的一个,控制了发送方发送数据的速率

    • 以字节为单位的滑动窗口

      • TCP的滑动窗口是以字节为单位的,而非以报文为单位
      • 注意发过来的确认号的序号是字节的而不是分组的
      • 发送窗口表示在没有收到确认的情况下,发送方可以连续把窗口内的数据都发送出去,凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在重传的时候使用
      • 发送窗口的大小一定不能超过接收窗口的数值,除此之外还要考虑网络拥塞程度的制约
      • 发送窗口的构造:
        • 发送窗口后沿的后面部分表示已经发送且收到了确认,这些数据不再需要保留
        • 发送窗口前沿的前面部分则表示不允许发送,因为没有足够的缓存空间存放
      • 发送窗口的变化情况:
        • 后沿的变化情况:
          • 不动——没有收到新的确认
          • 前移——收到了新的确认
          • 后沿不可能向后移动,因为不能撤销掉已收到的确认
        • 前沿的变化情况:
          • 前移——收到了新的确认且窗口没有变小
          • 不动——没有收到新的确认且对方通知的窗口大小也不变或收到新的确认但对方通知的窗口缩小了
          • 可能发生向后收缩,例如通知的窗口缩小要远远大于确认的序号,就会导致必须后退,此时的方法可以等待接收窗口变大
        • 发送方的应用进程把字节流写入TCP的发送缓存,接收方的应用进程从TCP的接收缓存中读取字节流
        • 发送缓存:
          • 暂时存放:
            • 发送应用程序传送给发送方TCP准备发送的数据
            • TCP已发送出但尚未收到确认的数据
            • 发送窗口通常只是发送缓存的一部分,已被确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的
          • 发送应用程序最后写入发送缓存的字节减去最后被确认的字节就是还保留在发送缓存中的被写入的字节数
        • 接收缓存:
          • 暂时存放:
            • 按序到达的、但尚未被接受应用程序读取的数据
            • 未按序到达的数据
          • 如果收到的分组被检测出有差错,就要丢弃
        • 强调:
          1. 虽然发送方的发送窗口是根据接收方的接收窗口设置的,但同一时刻发送方的发送窗口并不总是和接收方的接收窗口一样大,原因是网络具有滞后性,同时还要根据网络当时的拥塞情况适当减小自己的发送窗口数值
          2. 对于不按序到达的数据,TCP通常是把不按需到达的数据先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程
          3. TCP要求接收方必须有累积确认的功能,可以减小传输开销
            • 接收方可以在合适的时候(标准规定确认推迟的时间不应超过0.5s),或是在需要发送数据的时候把确认信息顺便捎带上
            • 若收到一连串具有最大长度的报文段,则必须每隔一个报文段就发送一个确认
  • HTTP

    • 为什么要使用 HTTP,而不直接使用 TCP

      • TCP 不够简洁,代码效率开发低
      • HTTP 可以使得开发关注于业务的本身
    • HTTP 1.1

      • 持续连接:万维网服务器在发送响应后仍然在一段时间内保持这条连接,是同一个客户(浏览器)和该服务器可以继续在这条连接上传送后续的HTTP请求报文和响应报文,避免了浪费资源
      • 分为两种工作方式
        • 非流水线方式
          • 客户收到前一个相应后才能发出下一个请求
          • 每访问一次对象都要用去一个往返时间RTT
          • TCP处于空闲状态,浪费了服务器资源
        • 流水线方式
          • 客户收到HTTP的响应报文之前就能够接着发送新的请求报文
          • 客户访问所有的对象都只需花费一个RTT时间
    • HTTP 2

      • 服务器发回的响应变成可以并行的发回
      • 允许客户复用TCP连接进行多个请求(多路复用)
        • 实际上还是串行,只是因为速度很快感觉上是并行
        • 丢包的话可能会发生队头阻塞,此时可以使用选项只重发丢失的报文段
      • 划分为许多较小的二进制编码的帧
    • QUIC

      • 基于 UDP 修改
      • 在 Userspace 用户端实现
      • 0 RTT
      • 弱网传输的优势(解决了队头阻塞的问题)
  • 数据中心

  • 网络提速:

    • 同运营商访问
    • 静态资源路径优化(CDN)
      • 边缘机房做一些缓存,如果有人访问过就直接发送,不需要再去访问内部的汇聚机房和核心机房
    • 动态 API(DSA)
      • 使用路径优化算法找到服务器和客户端之间的机房最短路径,可以通过如 BFS 算法完成
  • 容灾

    • 故障发生 -> 故障感知 -> 自动切换 -> 服务恢复
    • 应对措施:
      • 做储备

      • 不走外面的 Interenet,而是自己在机房建立专门的的物理连接专线,如果专线不可用,此时就使用外网容灾

      • 调度容灾:如果某个机房不可用了,此时就自动化完成地址的转换,使用其他的机房

      • 主动降级/容灾:

        • 如果是 Web 页面,此时没有办法嵌入 SDK,也无法容灾
        • 如果用户不让执行某些命令(需要授权),则无法使用
      • 前置兜底逻辑/cache 文件(bug 导致的 crash):如果发现后面不同,就直接使用之前的缓存

  • 故障排查:

    • 故障明确

      • 是什么业务、什么接口故障、故障体现在哪里、访问其他目标是正常、是否是修改导致的异常
    • 故障止损

      • 先止损再排查:对公司收入的影响是按照分钟甚至秒来计算
      • 如何止损:
        • 组件如果没有容灾
        • 降级相应的故障问题
    • 分段排查

      • 客户端排查

        • 客户端访问其他问题有没有问题
        • 其他客户端访问目标服务有没有问题
      • 服务端排查

        • 服务端监控和指标是否正常
        • 手动访问一下是否正常
        • 分组件排查(数据库、连接)
      • 中间链路排查

        • 中间网络设备有没有问题(交换机、路由器、网关 LB)
        • 旁路的 DNS 有没有问题
    • 故障排查常用命令:

      • dig 查询 DNS 问题