Java刷题知识点之拥塞发生的主要原因、TCP拥塞控制、TCP流量控制、TCP拥塞控制的四大过程(慢启动、拥塞避免、快速重传、快速恢复)

简介:

什么是拥塞?

  当大量的分组进入通信子网,超出了网络的处理能力时,就会引起网络局部或整体性能下降,这种现象称为拥塞。拥塞常常使问题趋于恶化。

       另一种对拥塞的解释,即对资源的需求超过了可用的资源。若网络中许多资源同时供应不足,网络的性能就要明显变坏,整个网络的吞吐量随之负荷的增大而下降。

 

 

 

 

 

拥塞的发生与其不可避免   
   拥塞发生的主要原因在于网络能够提供的资源不足以满足用户的需求,这些资源包括缓存空间、链路带宽容量和中间节点的处理能力。由于互联网的设计机制导致其缺乏“接纳控制”能力,因此在网络资源不足时不能限制用户数量,而只能靠降低服务质量来继续为用户服务,也就是“尽力而为”的服务

  拥塞其实是一个动态问题,我们没有办法用一个静态方案去解决,从这个意义上来说,拥塞是不可避免的

 

  静态解决问题办法1:
例如:增加缓存空间到一定程度时,只会加重拥塞,而不是减轻拥塞,这是因为当数据包经过长时间排队完成转发时,它们很可能早已超时,从而引起源端超时重发,而这些数据包还会继续传输到下一路由器,从而浪费网络资源,加重网络拥塞。事实上,缓存空间不足导致的丢包更多的是拥塞的“症状”而非原因。另外,增加链路带宽及提高处理能力也不能解决拥塞问题。
  静态解决问题办法2:
例如:我们有四台主机ABCD连接路由器R,所有链路带宽都是1Gbps,如果A和B同时向C以1Gbps的速率发送数据,则路由器R的输入速率为2Gbps,而输出速率只能为1Gbps,从而产生拥塞。避免拥塞的方法只能是控制AB的速率,例如,都是0.5Gbps,但是,这只是一种情况,倘若D也向R发送数据,且速率为1Gbps,那么,我们先前的修正又是不成立的。

 

 

 

 

拥塞控制和流量控制的差别
       所谓 拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能承受现有的网络负荷。
        流量控制往往指的是点对点通信量的控制,是个端到端的问题。流量控制所要做的就是控制发送端发送数据的速率,以便使接收端来得及接受。
 
 
 

 

 

TCP的拥塞控制   

  为什么需要拥塞控制?

  答:由于TCP采用了超时重传机制,如果拥塞不加以控制,将导致大量的报文重传,并再度引起大量的数据报丢弃,直到整个网络瘫痪。这种现象称为拥塞崩溃。

  在网络实际的传输过程中,会出现拥塞的现象,网络上充斥着非常多的数据包,但是却不能按时被传送,形成网络拥塞,其实就是和平时的堵车一个性质了。TCP设计中也考虑到这一点,使用了一些算法来检测网络拥塞现象,如果拥塞产生,变会调整发送策略,减少数据包的发送来缓解网络的压力。

 

       拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提:网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。

 

 

 

 

 

TCP的流量控制   
  • 早期的TCP协议只有基于窗口的流控制(flow control)机制,我们简单介绍一下,并分析其不足。   在TCP中,为了实现可靠性,发送方发出一个数据段之后要等待接受方相应的确认信息,而不是直接发送下一个分组。
  • 具体的技术是采用滑动窗口,以便通信双方能够充分利用带宽。滑动窗口允许发送方在收到接收方的确认之前发送多个数据段。窗口大小决定了在收到目的地确认之前,一次可以传送的数据段的最大数目。窗口大小越大,主机一次可以传输的数据段就越多。当主机传输窗口大小数目的数据段后,就必须等收到确认,才可以再传下面的数据段。例如,若视窗的大小为 1,则传完数据段后,都必须经过确认,才可以再传下一个数据段;当窗口大小等于3时,发送方可以一次传输3个数据段,等待对方确认后,再传输下面三个数据段。  
  •  窗口的大小在通信双方连接期间是可变的,通信双方可以通过协商动态地修改窗口大小。在TCP的每个确认中,除了指出希望收到的下一个数据段的序列号之外,还包括一个窗口通告,通告中指出了接收方还能再收多少数据段(我们可以把通告看成接收缓冲区大小)。如果通告值增大,窗口大小也相应增大;通告值减小,窗口大小也相应减小。但是我们可以发现,接收端并没有特别合适的方法来判断当前网络是否拥塞,因为它只是被动得接收,不像发送端,当发出一个数据段后,会等待对方得确认信息,如果超时,就可以认为网络已经拥塞了。
  • 所以,改变窗口大小的唯一根据,就是接收端缓冲区的大小了。   
  • 流量控制作为接受方管理发送方发送数据的方式,用来防止接受方可用的数据缓存空间的溢出。
  • 流控制是一种局部控制机制,其参与者仅仅是发送方和接收方,它只考虑了接收端的接收能力,而没有考虑到网络的传输能力;
  • 而拥塞控制则注重于整体,其考虑的是整个网络的传输能力,是一种全局控制机制。正因为流控制的这种局限性,从而导致了拥塞崩溃现象的发生。  

 

 

 

 

 

 

TCP拥塞控制的四大过程(慢启动、拥塞避免、快速重传、快速恢复)

  TCP的拥塞控制由4个核心算法组成:“慢启动”(Slow Start)、“拥塞避免”(Congestion voidance)、“快速重传 ”(Fast Retransmit)、“快速恢复”(Fast Recovery)。

   为了方便起见,把发送端叫做client,接收端为server,每个segment长度为512字节,阻塞窗口长度为cwnd(简化起见,下面以segment为单位),sequence number为seq_num,acknowledges number为ack_num。通常情况下,TCP每接收到两个segment,发送一个ack。

 

 

 

 

  (1)慢启动    
  早期开发的TCP应用在启动一个连接时会向网络中发送大量的数据包,这样很容易导致路由器缓存空间耗尽,网络发生拥塞,使得TCP连接的吞吐量急剧下降。由于TCP源端一开始并不知道网络资源当前的利用状况,因此新建立的TCP连接不能一开始就发送大量数据,而只能逐步增加每次发送的数据量,以避免上述现象的发生,这里有一个“学习”的过程。    假设client要发送5120字节到server,
  慢启动过程如下:   
    1、初始状态,cwnd=1,seq_num=1;client发送第一个segment。  
    2、server接收到512字节(一个segment),回应ack_num=513。
    3、client接收ack(513),cwnd=1+1=2;现在可以一次发送2个数据段而不必等待ack。   
    4、server接收到2个segment,回应ack_num=513+512*2=1537  。 
    5、client接收ack(1537),cwnd=2+1;一次发送3个数据段   。
    6、server接收到3个segment,回应2个ack,分别为ack_num=1537+1024=2561和ack_num=2561+512=3073   。
    7、client接收ack(2561)和ack(3073),cwnd=3+2=5;一次可以发送5个数据段,但是只用4个就满足要求了   。
    8、server接收到4个segment,回应2个ack,分别为4097,5121   9.已经发送5120字节,任务完成!
   总结一下: 当建立新的TCP连接时,拥塞窗口(congestion window,cwnd)初始化为一个数据包大小。源端按cwnd大小发送数据,每收到一个ACK确认,cwnd就增加一个数据包发送量。  

 

 

(1)慢启动算法是一个在连接上发起数据流的方法。

(2)慢启动过程:

         初始时将拥塞窗口的初始为一个MSS,每次收到一个报文段的确认时发送方将拥塞窗口增大一个MSS,并发送两个最大长度的报文段。两个报文段被确认后,则发送方复每个报文段的确认增加一个MSS,使得拥塞窗口变为4个MSS,这样每过一个RTT,发送速率就翻番。因此,在慢启动阶段以指数增长。

(3)慢启动的结束:

          当出现一个由超时指示的丢包事件,TCP发送方将cwnd设置为1,并重新开始慢启动。

 

 

 

 

 

  (2) 拥塞避免  
    可以想象,如果按上述慢启动的逻辑继续下去而不加任何控制的话,必然会发生拥塞,引入一个慢启动阈值ssthresh的概念,当cwnd<ssthresh的时候,tcp处于慢启动状态,否则,进入拥塞避免阶段。通常,ssthresh初始化为 64 Kbytes。    当cwnd = 64947 + 512 = 65459,进入拥塞避免阶段,假设此时seq_num = _101024:   
  1、client一次发送cwnd,但是先考虑头两个segment  。
     2、server回应ack_num = 102048   。
  3、client接收到ack(102048),cwnd = 65459 + [(512 * 512) /65459] = 65459 + 4 = 65463,也就是说,每接到一个ack,cwnd只增加4个字节。   
  4、client发送一个segment,并开启ack timer,等待server对这个segment的ack,如果超时,则认为网络已经处于拥塞状态,则重设慢启动阀值ssthresh=当前cwnd/2=65463/2=32731,并且,立刻把cwnd设为1,很极端的处理!
   5.此时,cwnd<ssthresh,所以,恢复到慢启动状态。
   总结一下:如果当前cwnd达到慢启动阀值,则试探性的发送一个segment,如果server超时未响应,TCP认为网络能力下降,必须降低慢启动阀值,同时,为了避免形势恶化,干脆采取极端措施,把发送窗口降为1,个人感觉应该有更好的方法。
 
 
 

(1)拥塞避免算法是一种处理丢失分组的方法。(当到达中间路由器的极限时,分组将被丢弃。)

(2)拥塞避免过程:

         进入拥塞避免时,拥塞窗口的值大约是上次遇到拥塞时值的一半,每个RTT只将拥塞窗口的值增加1个MSS.

(3)结束条件:超时或丢包。

 

 

 

 

 

  (3)(4)快速重传和快速恢复    
  前面讲过标准的重传,client会等待RTO时间再重传,但有时候,不必等这么久也可以判断需要重传,
快速重传
  例如:client一次发送8个segment,seq_num起始值为100000,但是由于网络原因,100512丢失,其他的正常,则server会响应4个ack(100512)(为什么呢,tcp会把接收到的其他segment缓存起来,ack_num必须是连续的),这时候,client接收到四个重复的ack,它完全有理由判断100512丢失,进而重传,而不必傻等RTO时间了。   
  快速恢复
  我们通常认为client接收到3个重复的ack后,就会开始快速重传,但是,如果还有更多的重复ack呢,如何处理?这就是快速恢复要做的,事实上,我们可以把快速恢复看作是快速重传的后续处理,它不是一种单独存在的形态。   
 
以下是具体的流程:  
  假设此时cwnd=70000,client发送4096字节到server,也就是8个segment,起始seq_num = _100000:   
  1、client发送seq_num = _100000   。
  2、seq_num =100512的segment丢失  。 
  3、client发送seq_num = _101024   。
  4、server接收到两个segment,它意识到100512丢失,先把收到的这两个segment缓存起来  。 
  5、server回应一个ack(100512),表示它还期待这个segment  。
  6、client发送seq_num = _101536   。
  7、server接收到一个segment,它判断不是100512,依旧把收到的这个segment缓存起来,并回应ack(100512)  。
  8、以下同6、7,直到client收到3个ack(100512),进入快速重发阶段。   
  9、重设慢启动阀值ssthresh=当前cwnd/2=70000/2=35000   。
  10、client发送seq_num = 100512     以下,进入快速恢复阶段。   
  11、重设cwnd = ssthresh + 3 segments =35000 + 3*512 = 36536,之所以要加3,是因为我们已经接收到3个ack(100512)了,
              根据前面说的,每接收到一个ack,cwnd加1   。
  12、client接收到第四个、第五个ack(100512),cwnd=36536+2*512=37560  。
    13、server接收到100512,响应ack_num = _104096   14.此时,cwnd>ssthresh,进入拥塞避免阶段。

 

 

(1)执行条件及过程

     当收到3个或3个以上的重复ACK时,就非常有可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而不等待超时定时器溢出。这就是快速重传。接下来执行的不是慢启动,而是拥塞避免,这就是快速恢复。

(2)原因:

    没有执行慢启动的原因是由于收到的重复的ACK不仅仅告诉我们一个分组丢失了。由于接收方只有在收到另一个报文段时才会产生重复的ACK,而该报文段已经离开网络并进入了接收方的缓存。也就是说在收发两端之间仍然有流动的数据,而我们不想执行慢启动来突然减少数据流。

 

 

 

 

 

 

  真实例子

  想想看,能不能把TCP解决拥塞的方法应用到交通拥塞呢?   我们有两个原则:一是拥塞不可避免,单纯增加资源并不能避免拥塞的发生,只能用动态的方法加以解决;二是数据包守恒原则。政府花费很大资金修路,并不能避免堵车,只能从源头控制,例如首先限制车辆进入主路,根据实际情况,再慢慢增加每一个路口的车流量,但是,当达到一个阀值,增加速度要放缓,并不时探测整个主路的拥堵情况,如果情况危急,立刻封闭半个路口,并将车流量降到最低,也就是重新回复到慢启动状态。   呵呵,有趣!



本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/7617819.html,如需转载请自行联系原作者

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
227 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
4月前
|
存储 Java 程序员
Java 基础知识点全面梳理包含核心要点及难点解析 Java 基础知识点
本文档系统梳理了Java基础知识点,涵盖核心特性、语法基础、面向对象编程、数组字符串、集合框架、异常处理及应用实例,帮助初学者全面掌握Java入门知识,提升编程实践能力。附示例代码下载链接。
195 0
|
4月前
|
Java 编译器 数据安全/隐私保护
Java 大学期末考试真题与答案 含知识点总结 重难点归纳及题库汇总 Java 期末备考资料
本文汇总了Java大学期末考试相关资料,包含真题与答案、知识点总结、重难点归纳及题库,涵盖Java基础、面向对象编程、异常处理、IO流等内容,并提供完整代码示例与技术方案,助你高效复习备考。
237 3
|
4月前
|
存储 缓存 安全
Java基础 - 知识点
Java基础知识点涵盖语言特性、面向对象与基本数据类型、缓存池机制、String类特性、参数传递、类型转换、继承、抽象类与接口区别、重写与重载、Object通用方法及关键字使用等核心内容,是掌握Java编程的重要基石。
|
5月前
|
存储 安全 Java
2025 年最新 40 个 Java 基础核心知识点全面梳理一文掌握 Java 基础关键概念
本文系统梳理了Java编程的40个核心知识点,涵盖基础语法、面向对象、集合框架、异常处理、多线程、IO流、反射机制等关键领域。重点包括:JVM运行原理、基本数据类型、封装/继承/多态三大特性、集合类对比(ArrayList vs LinkedList、HashMap vs TreeMap)、异常分类及处理方式、线程创建与同步机制、IO流体系结构以及反射的应用场景。这些基础知识是Java开发的根基,掌握后能为后续框架学习和项目开发奠定坚实基础。文中还提供了代码资源获取方式,方便读者进一步实践学习。
1604 2
|
5月前
|
并行计算 Java API
Java 入门循环结构基础知识点详解
摘要:本文介绍了Java现代循环技术的进阶应用,包括Stream API、响应式编程和模式匹配,展示了如何用Stream API替代传统循环进行声明式集合处理(如过滤、映射和并行计算),以及响应式编程在异步非阻塞场景下的优势。文章还通过电商订单处理系统的案例演示了这些技术的综合应用,并提供了性能优化建议,如合理使用并行处理和避免循环内对象创建。这些现代特性使Java代码更简洁、高效,更适合高并发和I/O密集型场景。
85 1
|
5月前
|
缓存 算法 NoSQL
校招 Java 面试高频常见知识点深度解析与实战案例详细分享
《2025校招Java面试核心指南》总结了Java技术栈的最新考点,涵盖基础语法、并发编程和云原生技术三大维度: 现代Java特性:重点解析Java 17密封类、Record类型及响应式Stream API,通过电商案例演示函数式数据处理 并发革命:对比传统线程池与Java 21虚拟线程,详解Reactor模式在秒杀系统中的应用及背压机制 云原生实践:提供Spring Boot容器化部署方案,分析Spring WebFlux响应式编程和Redis Cluster缓存策略。
147 0
|
4月前
|
缓存 安全 前端开发
Java 核心知识点与实战应用解析
我梳理的这些内容涵盖了 Java 众多核心知识点。包括 final 关键字的作用(修饰类、方法、变量的特性);重载与重写的区别;反射机制的定义、优缺点及项目中的应用(如结合自定义注解处理数据、框架底层实现)。 还涉及 String、StringBuffer、StringBuilder 的差异;常见集合类及线程安全类,ArrayList 与 LinkedList 的区别;HashMap 的实现原理、put 流程、扩容机制,以及 ConcurrentHashMap 的底层实现。 线程相关知识中,创建线程的四种方式,Runnable 与 Callable 的区别,加锁方式(synchronize
102 0
|
5月前
|
存储 设计模式 Java
Java 期末考试不挂科必背基础知识点复习笔记整理
这是一份全面的Java基础知识点复习笔记,涵盖核心特性、数据类型、流程控制、数组、异常处理、JVM原理、多线程、设计模式及Java 8+新特性等内容。结合买飞机票、验证码生成和评委打分等应用实例,助你掌握考试重点,轻松应对Java期末考试,避免挂科!附带代码资源,供深入学习使用。链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)
172 0
下一篇
oss云网关配置