当前位置: 首页 > news >正文

TCP拥塞控制详解 | 6. 主动队列管理

网络传输问题本质上是对网络资源的共享和复用问题,因此拥塞控制是网络工程领域的核心问题之一,并且随着互联网和数据中心流量的爆炸式增长,相关算法和机制出现了很多创新,本系列是免费电子书《TCP Congestion Control: A Systems Approach》的中文版,完整介绍了拥塞控制的概念、原理、算法和实现方式。原文: TCP Congestion Control: A Systems Approach[1]

alt

第6章 主动队列管理(Active Queue Management)

现在我们来看看路由器在拥塞控制中扮演的角色,这种方法通常被称为主动队列管理(AQM, Active Queue Management) 。就其本质而言,AQM引入了一个避免端到端解决方案的元素,即使与TCP Reno等基于控制的方法配合也能发挥作用。

尽管对路由器行为的改变从来不是互联网引入新功能的首选方式,但在过去30年里,这种方法始终令人感到紧张。问题在于,虽然人们普遍认为路由器处于检测拥塞开始的理想位置(即队列开始被填满),但对于什么才是最佳算法并没有达成一致意见。下面介绍了两种经典机制,并简要讨论了目前的情况。

6.1 DECbit

第一种机制是为数字网络体系架构(DNA, Digital Network Architecture)开发的,它是TCP/IP互联网的早期竞争者,也采用了无连接/尽力而为网络模型,由K.K. Ramakrishnan和Raj Jain共同发明,和Jacobson/Karels的论文同时发表在1988年的SIGCOMM会议。

延伸阅读:
K.K. Ramakrishnan and R. Jain. A Binary Feedback Scheme for Congestion Avoidance in Computer Networks with a Connectionless Network Layer[2]. ACM SIGCOMM, August 1988.

其想法是在路由器和终端主机之间更均匀的分担拥塞控制的责任。每个路由器监控正在处理的负载,并在拥塞即将发生时显式通知终端节点。这个通知是通过在流经路由器的数据包中设置一个二进制拥塞位来实现的,这个二进制拥塞位后来被称为DECbit。然后,目标主机将这个拥塞位复制到ACK中返回给发送端。最后,发送端通过调整发送速率避免拥塞。下面将从路由器开始详细的介绍该算法。

在包报头中增加一个拥塞位,如果数据包到达时,路由器的平均队列长度大于或等于1,则设置此位。平均队列长度是在跨越上一个繁忙/空闲周期,再加上当前繁忙周期的时间间隔内测量的。(路由器忙指的是正在传输数据,空闲指的是没有传输数据。) 图34显示了路由器上的队列长度随时间的变化。实际上,路由器将计算曲线下的面积,并将该值除以时间间隔来计算平均队列长度。使用队列长度为1作为设置拥塞位的触发器是在有大量排队(从而吞吐量较高)和大量空闲时间(从而延迟较低)之间的权衡。换句话说,长度为1的队列似乎优化了幂函数。

图34. 计算路由器的平均队列长度。
图34. 计算路由器的平均队列长度。

现在我们把注意力转移到该机制与主机相关的部分,发送端记录有多少包导致路由器设置了拥塞位,就像在TCP中一样维护了一个拥塞窗口,并观察最后一个窗口的数据包值中有多少导致拥塞位被设置。如果少于50%的包设置了拥塞位,则发送端的拥塞窗口就增加一个包。如果上一个窗口值的50%或更多的包设置了拥塞位,则发送端的拥塞窗口减小到前一个值的0.875倍。经过分析,选择50%作为阈值,与幂曲线的峰值相对应。之所以选择"增加1,减少0.875"规则,是因为线性增加/指数减少使机制更稳定。

6.2 随机早期检测(Random Early Detection)

第二种机制被称为随机早期检测(RED, Random Early Detection) ,类似于DECbit方案,每个路由器都被编程来监控自己的队列长度,当检测到拥塞即将发生时,通知发送端调整拥塞窗口。RED是由Sally Floyd和Van Jacobson在20世纪90年代早期发明的,与DECbit方案的不同之处在于以下两点。

延伸阅读:
S. Floyd and V. Jacobson Random Early Detection (RED) Gateways for Congestion Avoidance[3]. IEEE/ACM Transactions on Networking. August 1993.

首先,RED并不向发送端显示发送拥塞通知消息,而是丢弃一个包,通过后续的超时或重复ACK来隐式通知发送端。也许你会猜到,RED被设计成与TCP一起使用,TCP目前就是通过超时(或其他检测丢包的方法,比如重复ACK)来检测拥塞。正如RED首字母缩写的"早期"所暗示的那样,网关必须在不得不丢弃数据包之前丢弃数据包,以便通知发送端比正常情况下更早的减少拥塞窗口。换句话说,路由器在缓冲区空间完全耗尽之前通过丢弃部分数据包,从而使得发送端速度变慢,避免今后丢弃大量数据包。

RED和DECbit的第二个区别在于RED如何决定何时丢弃一个包以及丢弃什么包。为了理解基本思想,考虑一个简单的FIFO队列,与其等待队列完全填满,然后被迫丢弃每个到达的包(在第2.1.3节中描述的尾丢弃策略),我们可以决定在队列长度超过某个丢弃级别(drop level) 时,以一定的概率丢弃到达的包,这一理念被称为早期随机丢包(early random drop) 。RED算法定义了如何监控队列长度以及何时丢包的细节。

下面我们将介绍由Floyd和Jacobson最初提出的RED算法。我们注意到,发明者和其他研究人员已经提出了一些修改意见,然而,关键思想仍然与下面介绍的一样,而且当前大多数实现都接近下面的算法。

首先,RED使用与原始TCP超时计算中使用的加权运行平均值来计算平均队列长度,即AvgLen

其中0 < Weight < 1, SampleLen为采样测量时的队列长度。在大多数软件实现中,每次有新数据包到达网关时都测量队列长度,在硬件中,可以以某个固定的采样间隔进行计算。

使用平均队列长度而不是瞬时队列长度的原因是它能够更准确的体现拥塞。由于互联网流量的爆发式特性,队列可能很快被塞满,然后又快速被清空。如果一个队列大部分时间都是空的,那么就不应该认为发生了拥塞。因此,加权运行平均计算试图通过过滤掉队列长度的短期变化来检测长期拥塞,如图35的右边部分所示。可以把运行平均值想象成低通滤波器,其中Weight决定滤波器的时间常数,如何选择这个时间常数的问题将在下面讨论。

图35. 加权运行平均队列长度。
图35. 加权运行平均队列长度。

其次,RED有两个触发特定活动的队列长度阈值: MinThresholdMaxThreshold。当报文到达网关时,RED将当前AvgLen与这两个阈值按照如下规则进行比较:

if AvgLen <= MinThreshold 
    queue the packet 
if MinThreshold < AvgLen < MaxThreshold 
    calculate probability P 
    drop the arriving packet with probability P 
if MaxThreshold <= AvgLen 
    drop the arriving packet 

如果平均队列长度小于下限阈值,则不采取任何措施;如果平均队列长度大于上限阈值,则始终丢弃报文。如果平均队列长度在两个阈值之间,那么新到达的数据包以一定的概率P被丢弃,如图36所示。PAvgLen的近似关系如图37所示。注意,当AvgLen处于两个阈值之间时,丢包概率会缓慢增加,在上限达到MaxP时,就会丢弃所有包。这背后的基本原理是,如果AvgLen达到了上阈值,那么温和的方法(丢弃一些包)就不起作用,需要采取严厉的措施,即丢弃所有到达的包。这里介绍的方法是从随机丢包直接跳跃到完全丢包,不过一些研究表明,从随机丢包平稳过渡到完全丢包可能更合适。

图36. FIFO队列的RED阈值。
图36. FIFO队列的RED阈值。
图37. RED的丢包概率函数。
图37. RED的丢包概率函数。

尽管图37显示的丢包概率只是AvgLen的一个函数,但实际情况要复杂一些。实际上,PAvgLen以及最后一个丢包到现在的时间的函数。具体计算方法如下:

TempP是在图37中y轴上的变量,count计算排队(没有被丢弃)的新包,AvgLen位于两个阈值之间。P随着count的增加而缓慢增加,因此距离上一次丢包的时间越长,发生丢包的可能性就越来越大。这使得频繁丢包的可能性比间隔较长时间丢包的可能性更低。这个计算P的额外步骤是由RED的发明者引入的,他们观察到,如果没有这一参数,丢包就不能均匀分布,而是倾向于在集中发生。由于某个连接的数据包很可能是突然到达的,这种集中丢包很可能造成单个连接丢弃大量包,而这并不可取。每次往返时间发生一次丢包就足以导致连接减少窗口大小,而多次丢包可能会导致发送端切换到慢启动。

举个例子,假设我们将MaxP设置为0.02,count初始化为0。如果平均队列长度在两个阈值中间,那么TempPP的初始值将是MaxP的一半,即0.01,意味着此时到达的数据包有99%的机会进入队列。随着每收到一个没有被丢弃的连续数据包,P会慢慢增加,当50个没有丢弃的数据包到达时,P会翻倍到0.02。虽然不太可能,但如果99个包都到达而没有丢包,P将变为1,从而保证下一个包一定会被丢弃。这部分算法的重要之处在于,可以确保随着时间的推移,丢包的分布大致均匀。

其目的是,当AvgLen超过MinThreshold时,如果RED丢弃一小部分数据包,导致某些TCP连接减少窗口大小,从而减少数据包到达路由器的速率。一切顺利的话,AvgLen将会变小,从而避免拥塞。这样可以保持较短的队列长度,同时维持较高的吞吐量。

注意,因为RED操作的是随时间变化的平均队列长度,所以瞬时队列长度可能比AvgLen长得多。在这种情况下,如果收到了一个包,但没有地方放它,那将不得不丢弃。当这种情况发生时,RED的行为和尾丢包模式一致。RED的目标之一是,在可能的条件下尽量避免尾丢包行为。

RED的随机性赋予了算法一个有趣的特性。因为RED是随机丢包的,所以决定丢弃特定流的包的概率大致与流在当前路由器上获得的带宽份额成正比。这是因为发送相对较多的包的流为随机丢弃提供了更多的候选者。因此,尽管并不精确,但RED具有某种公平的资源分配策略。虽然可以说是公平的,但因为RED对高带宽流的影响大于对低带宽流的影响,这增加了TCP重启的可能性,从而有可能对高带宽流造成额外的影响。

为了优化幂函数(吞吐量-延迟比),我们对各种RED参数进行了大量分析,例如MaxThresholdMinThresholdMaxPWeight,通过仿真验证了这些参数的性能,结果表明算法对这些参数不太敏感。但是,所有这些分析和模拟都取决于网络工作负载的特定表征。RED的真正贡献是提出了一种路由器可以更准确管理其队列长度的机制,而对于不同的流量组合的最优排队长度还是一个正在研究的课题。

考虑两个阈值MinThresholdMaxThreshold的设置。如果流量相当大,那么MinThreshold应该足够大,以允许链路利用率保持一个可接受的高水平。此外,两个阈值之间的差值应该大于一个RTT中计算的平均队列长度的典型增长值。对于今天的互联网流量模型来说,将MaxThreshold设置为MinThreshold的两倍似乎比较合理。此外,由于我们期望平均队列长度在高负载期间可以在两个阈值之间波动,因此在MaxThreshold之上应该有足够的空闲缓冲区空间来吸收突发的互联网流量,避免路由器被迫进入尾丢包模式。

上面提到Weight决定了运行平均低通滤波器的时间常数,从而为如何选择合适的Weight值提供了线索。回想一下,RED试图在拥塞期间通过丢包向TCP流发送信号。假设路由器丢弃了来自某个TCP连接的数据包,然后立即转发来自同一连接的更多数据包。当这些包到达接收端时,开始向发送端发送重复的ACK。当发送端看到足够多的重复ACK时,将减少窗口大小。因此,路由器从丢弃一个数据包直到开始看到受影响连接的窗口大小有所减少,该连接至少需要一个往返时间。如果路由器对拥塞的响应时间比连接往返时间短得多,可能没有多大意义。正如前面提到的,100ms是对互联网平均往返时间的一个不错的估算。因此,Weight的选择应该能够过滤掉小于100ms的队列长度变化。

由于RED通过向TCP流发送信号来通知它们减速,你可能想知道如果忽略这些信号会发生什么,这通常被称为无响应流(unresponsive flow) 问题。无响应流使用的网络资源超过了公平的份额,就像没有TCP拥塞控制那样,如果有很多无响应流,可能会导致拥塞崩溃。一些排队技术,如加权公平排队,可以通过隔离某些类别的流量来帮助解决这个问题。还有一些讨论考虑创建RED的变体,对于无响应流丢弃更多的包。然而,挑战性在于,很难区分非响应行为和"正确"行为,特别是当流具有各种不同的RTT和瓶颈带宽时。

作为一个注脚,15位著名的网络研究人员在1998年敦促广泛采用受RED启发的AQM。这一建议在很大程度上被忽略了,原因我们将在下文谈到。然而,基于RED的AQM方法已经在数据中心得到了一些成功的应用。

延伸阅读:
R. Braden, et al. Recommendations on Queue Management and Congestion Avoidance in the Internet[4]. RFC 2309, April 1998.

6.3 可控延迟(Controlled Delay)

如上一节所述,RED从未被广泛采用,当然,也从来没有达到对互联网拥塞产生重大影响的必要水平。一个原因是,RED很难以一种增量的方式进行配置。影响其操作的参数有很多(MinThresholdMaxThresholdWeight),有足够的研究表明,RED会根据流量类型和参数设置产生不同的结果(并非所有结果都是有益的),这就造成了对RED的部署有不确定性。

在过去一段时间里,Van Jacobson(因其在TCP拥塞方面的工作和最初的RED论文的合著者而闻名)与Kathy Nichols和其他研究人员合作,最终提出了一种改进RED的AQM方法。这项工作被称为CoDel(发音为coddle)控制延迟(Controlled Delay) AQM,其基础建立对TCP和AQM几十年研究经验的关键见解上。

延伸阅读:
K. Nichols and V. Jacobson. Controlling Queue Delay[5]. ACM Queue, 10(5), May 2012.

首先,队列是网络的重要组成部分,网络中时不时的就会有队列堆积。例如,新打开的连接可能会将一个窗口的数据包发送到网络中,可能会在瓶颈链路处形成队列。这本身不是问题,网络应该有足够的缓冲能力来吸收这样的突发流量。但如果没有足够的缓冲能力时,就会出现问题,导致过量丢包。在20世纪90年代,这被理解为一种需求,即缓冲区至少能够保存一个带宽时延积的包,这一要求可能太大了,随后受到进一步研究的质疑。但事实是,用来吸收突发流量的缓冲区是必要的。CoDel的作者将其称为"好队列",如图38 (a)所示。

图38. 好队列和坏队列场景。
图38. 好队列和坏队列场景。

当队列长期处于满状态时,就会成为问题。一个保持满的队列除了给网络增加延迟外什么用也没有,而且如果永远不会完全清空,吸收突发流量的能力也会降低。在这些缓冲区中,大型缓冲区和持久化队列的组合是一种现象,Jim Gettys将其命名为Bufferbloat。很明显,设计良好的AQM机制会试图避免长期满队列状态。不出意外,长时间保持满队列而无法清空的队列被称为"坏队列",如图38 (b)所示。

延伸阅读:
J. Gettys. Bufferbloat: Dark Buffers in the Internet[6]. IEEE Internet Computing, April 2011.

因此在某种意义上,AQM算法的挑战是区分"好"和"坏"队列,并且只有当确定队列是"坏"时才会触发丢包。实际上,这就是RED试图用weight参数(过滤掉暂态队列长度)做的事情。

CoDel的创新之一是关注停留时间(sojourn time): 任何给定包在队列中的等待时间。停留时间与链路带宽无关,即使在带宽随时间变化的链路(如无线链路)上,停留时间也能提供有用的拥塞指示。一个运行良好的队列将频繁清空,因此,数据包的停留时间接近于零,如图38 (a)所示。相反,拥塞队列将延迟每个数据包,并且最小停留时间永远不会接近于零,如图38 (b)所示。因此,CoDel测量停留时间(很容易对每个数据包采样),并跟踪其是否始终处于某个阈值之上,这一阈值被定义为"持续时间比典型RTT更长"。

该算法自己选择合理的默认值,而不要求运营商确定使CoDel正常工作的参数。算法使用5ms作为目标停留时间,以及100ms的滑动测量窗口。与RED一样,直觉上,100ms是互联网流量的典型RTT,如果拥塞持续时间超过100ms,可能会进入"坏队列"区域。所以CoDel监控相对于目标5ms的逗留时间,如果目标超过100ms,就是采取行动的时候,通过丢包减少队列(或显式标记拥塞通知)。选择5ms是因为接近于零(为了更好的延迟),但不会小到队列会会清空。值得注意的是,有关于这些数值选择的大量实验和模拟,但更重要的是,算法似乎对它们不太敏感。

总之,CoDel在很大程度上忽略了持续时间小于RTT的队列,但一旦队列持续时间超过RTT,就开始采取行动。该算法对互联网RTT进行了合理的假设,并且无需配置参数。

另一个微妙之处在于,只要观察到的停留时间保持在目标上方,CoDel就会缓慢增加丢包占流量的百分比。正如第7.4节中进一步讨论的那样,TCP吞吐量已被证明与丢包率的平方根成反比。因此,只要停留时间保持在目标上方,CoDel就会稳步增加丢包率,与丢包次数的平方根成正比。理论上,这样做的结果是导致受影响的TCP连接的吞吐量线性下降,最终将导致流量减少,从而允许队列清空,使停留时间回到目标以下。

图39. 家庭路由器可能会遭受缓冲区膨胀的影响,CoDel很适合解决这种情况。
图39. 家庭路由器可能会遭受缓冲区膨胀的影响,CoDel很适合解决这种情况。

在Nichols和Jacobson的论文中有更多关于CoDel的细节,包括大量模拟,表明其在各种场景中的有效性。该算法已经在RFC 8289中被IETF标准化为"实验性"算法,也实现在了Linux内核中,从而有助于它的部署。特别是,CoDel在家庭路由器(通常基于Linux)中提供了价值,这是端到端路径上的一个点(请参见图39),通常会受到缓冲区膨胀的影响。

6.4 显式拥塞通知

虽然TCP拥塞控制机制最初是基于丢包作为主要拥塞信号,但人们早就认识到,如果路由器发送更明确的拥塞信号,TCP可以做得更好。也就是说,与其丢弃一个数据包并假设TCP最终会注意到(例如,由于重复ACK的到来),如果能够标记数据包并继续将其发送到目的地,任何AQM算法都可以做得更好。这个想法体现在了IP和TCP报头的变化中,被称为显式拥塞通知(ECN, Explicit Congestion Notification) ,在RFC 3168中定义。

延伸阅读:
K. Ramakrishnan, S. Floyd, and D. Black. The Addition of Explicit Congestion Notification (ECN) to IP[7]. RFC 3168, September 2001.

具体来说,通过将IP TOS字段中的两个比特作为ECN比特来实现反馈机制。发送端设置一个比特表示具有ECN能力,即能够响应拥塞通知,这被称为ECT位(ECN-Capable Transport)。当发生拥塞时,另一个比特位由端到端路径上的路由器基于所运行的AQM算法计算并设置,被称为CE位(Congestion Encountered)。

除了IP报头中的这两位(与传输层无关),ECN还包括向TCP报头添加两个可选标志。一个是ECE(ECN-Echo),接收端通过设置这个选项向发送端表示其收到了一个设置了CE位的数据包。另一个是CWR(Congestion Window Reduced),发送端向接收端表示已经减小了拥塞窗口。

虽然ECN现在是IP报头TOS字段8位中的2位的标准定义,并且强烈建议支持ECN,但并不是必需的。此外,还没有推荐的AQM算法。好的AQM算法应该满足一系列要求,和TCP拥塞控制算法一样,每种AQM算法都有其优缺点,所以需要大量讨论。

6.5 入口/出口队列

我们已经在网络内部(即本章中介绍的AQM算法)和网络边缘(即前几章中介绍的基于TCP的算法)的拥塞控制方法之间画了一条清晰的线,但线条并不一是那么明确。要了解这一点,只需将端到端路径想象为在发送主机的内核/设备接口上有一个入口队列(ingress queue) ,在接收主机的设备/内核接口上有一个出口队列(egress queue)[1]。随着虚拟交换机和网卡对虚拟化的支持变得越来越普遍,这些边缘队列可能会变得越来越重要。

[1] 容易混淆的是,从网络路径的角度来看,入口队列是发送主机上的出站(出口)队列,而出口队列是接收主机上的入站(入口)队列。如图40所示,我们从网络的角度使用术语入口和出口。

图40展示了这一观点,两个队列都位于TCP之下,提供了向端到端路径注入第二段拥塞控制逻辑的机会。CoDel和ECN就是这个想法的例子,并且已经在Linux内核的设备队列级别实现。

图40. 分别在发送主机和接收主机上实现的端到端路径入口和出口队列。
图40. 分别在发送主机和接收主机上实现的端到端路径入口和出口队列。

这能起作用吗?一个问题是数据包是在入口丢弃还是在出口丢弃。当在入口(在发送主机上)丢弃时,TCP会在Write函数的返回值中收到通知,从而导致"忘记"发送了数据包,尽管TCP确实减少了拥塞窗口来响应失败的写操作,但接下来还会发送这个包。相反,在出口队列(在接收主机上)丢弃数据包,意味着TCP发送方将不知道重传数据包,直到使用其标准机制之一(例如,三个重复ACK或者超时)检测到丢包。当然,在出口实现ECN是有好处的。

当我们把这个讨论放在拥塞控制的大环境中考虑时,可以得出两个有趣的结论。首先,Linux提供了一种方便而安全的方式将新代码(包括拥塞控制逻辑)注入内核,即使用eBPF(extended Berkeley Packet Filter) 。eBPF在许多其他环境中也正在成为一项重要的技术。用于拥塞控制的标准内核API已经移植到eBPF,大多数现有的拥塞控制算法也已经移植到这个框架上。这简化了试验新算法的工作,也可以避开在Linux内核里部署现有算法优化的障碍。

延伸阅读:
The Linux Kernel. BPF Documentation.

其次,通过显式的将入口/出口队列暴露给决策过程,我们为构建拥塞控制机制打开了大门,该机制包含一个"决定何时传输数据包"的组件和一个"决定排队还是丢弃数据包"的组件。在第7.1节介绍On-Ramp时,我们会看到一个采用创新方法使用这两个组件的机制示例。

你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

参考资料

[1]

TCP Congestion Control: A Systems Approach: https://tcpcc.systemsapproach.org/index.html

[2]

A Binary Feedback Scheme for Congestion Avoidance in Computer Networks with a Connectionless Network Layer: https://dl.acm.org/doi/pdf/10.1145/52324.52355

[3]

Random Early Detection (RED) Gateways for Congestion Avoidance: http://www.icir.org/floyd/papers/early.twocolumn.pdf

[4]

Recommendations on Queue Management and Congestion Avoidance in the Internet: https://tools.ietf.org/html/rfc2309

[5]

Controlling Queue Delay: https://queue.acm.org/detail.cfm?id=2209336

[6]

Bufferbloat: Dark Buffers in the Internet: https://ieeexplore.ieee.org/document/5755608

[7]

The Addition of Explicit Congestion Notification (ECN) to IP: https://datatracker.ietf.org/doc/html/rfc3168

- END -

本文由 mdnice 多平台发布

相关文章:

TCP拥塞控制详解 | 6. 主动队列管理

网络传输问题本质上是对网络资源的共享和复用问题&#xff0c;因此拥塞控制是网络工程领域的核心问题之一&#xff0c;并且随着互联网和数据中心流量的爆炸式增长&#xff0c;相关算法和机制出现了很多创新&#xff0c;本系列是免费电子书《TCP Congestion Control: A Systems …...

前端学习清单

顺序不分先后。 技术名称技术描述技术链接HTML5HTML5是下一代的HTML标准&#xff0c;是一种用于结构化内容的标记语言。MDN|HTMLCSS3CSS3是CSS技术的升级版本&#xff0c;它的最大好处就是可以让网页设计师更加方便的为网页添加各种各样的样式&#xff0c;而不用再局限于文字、…...

go atomic原子操作详细解读

文章目录 概要1、基本知识1.1 原子操作是什么1.2 CPU怎么实现原子操作的&#xff1f; 2、atomic包2.1、 Add函数2.2、CompareAndSwap函数2.3、Swap函数2.4、Load函数2.5、Store函数 3、atomic.Value值 概要 atomic包是golang通过对底层系统支持的原子操作进行封装&#xff0c;…...

Vue用JSEncrypt对长文本json加密以及发现解密失败

哈喽 大家好啊&#xff0c;最近发现进行加密后 超长文本后端解密失败&#xff0c;经过看其他博主修改 JSEncrypt原生代码如下&#xff1a; // 分段加密&#xff0c;支持中文JSEncrypt.prototype.encryptUnicodeLong function (string) {var k this.getKey();//根据key所能编…...

Excel/PowerPoint折线图从Y轴开始(两侧不留空隙)

默认Excel/PowerPoint折线图是这个样子的&#xff1a; 左右两侧都留了大块空白&#xff0c;很难看 解决方案 点击横坐标&#xff0c;双击&#xff0c;然后按下图顺序点击 效果...

C++的类成员对齐

这是个小语法点&#xff0c;之前我们的对齐方式都是使用#pragma pack&#xff0c;这个方式实际是依赖编译器&#xff0c;且粒度粗(如果#pragma pack(1)之后没有#pragma pack(),那就作用整个进程了)。在C11之后引入关键字alignas&#xff0c;以此来实现对齐更加便利&#xff0c;…...

敏感挂载userhelper容器逃逸复现

目录 前言 分析 实验 前言 分析 实验 # Creates a payload cat "#!/bin/sh" > /evil-helper cat "ps > /output" >> /evil-helper chmod x /evil-helper # Finds path of OverlayFS mount for container # Unless the configuration ex…...

深度解读Promise.prototype.finally

由一个问题引发的血案&#xff1a; 手写源码实现Promise.prototype.finally。 我们知道&#xff0c;对于promise来讲&#xff0c;当状态敲定&#xff0c;无论状态兑现或拒绝时都需要调用的函数&#xff0c;可以使用Promise.prototype.finally的回调来实现。那么如何手写实现Pro…...

如何实现24/7客户服务自动化?建设智能客服知识库

客户自助服务是指用户通过企业或者第三方建立的网络平台或者终端&#xff0c;实现相关的自定义处理。实现客户服务自动化&#xff0c;对提高客户满意度、维持客户关系至关重要。客户服务自动化可以帮助企业以更快的速度和更高的效率来满足客户的售后服务要求&#xff0c;以进一…...

和鲸 ModelWhale 与中科可控多款服务器完成适配认证,赋能中国云生态

当前世界正处于新一轮技术革命及传统产业数字化转型的关键期&#xff0c;云计算作为重要的技术底座&#xff0c;其产业发展与产业规模对我国数字经济的高质量运行有着不可取代的推动作用。而随着我国数字上云、企业上云加快进入常规化阶段&#xff0c;云计算承载的业务应用越来…...

selenium +Jmeter 的性能测试

通过Jmeter快速将已有的Selenium 代码以性能测试的方式组织起来&#xff0c;并使用JMeter 丰富的报表展示测试结果 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By driver …...

探索高效的HTTP异步接口测试方法:从轮询等待到自动化方案

本文将深入探讨HTTP异步接口测试的多个方面&#xff0c;包括轮询等待、性能测试以及自动化方案。通过详细的解释和实际案例&#xff0c;帮助您了解如何有效地测试异步接口&#xff0c;确保系统的稳定性和性能。 在现代软件开发中&#xff0c;HTTP异步接口扮演着至关重要的角色&…...

Android资深工程书之LiveData核心组件原理剖析

LiveData是Android架构组件库中的一个类&#xff0c;用于在应用程序组件之间共享数据。它是一种可观察的数据持有者&#xff0c;可以感知应用程序组件的生命周期&#xff0c;并在数据发生变化时通知观察者。 使用LiveData 在Android应用程序中使用LiveData&#xff0c;你可以…...

Vue的五种方法实现加减乘除运算

五种方法的详细说明&#xff1a; 计算属性&#xff08;Computed Properties&#xff09;&#xff1a; 计算属性是Vue.js提供的一种便捷的属性&#xff0c;它根据依赖的数据动态计算出一个新的值。计算属性的值会被缓存&#xff0c;只有当依赖的数据发生变化时&#xff0c;才会…...

C++(1)Linux基础知识

经济下行&#xff0c;计算机就业形势严峻&#xff0c;为了勉励自己继续进步&#xff0c;继续学习代码提高核心竞争力。 安装QT Creator 首先&#xff0c;安装QT开发工具QT Creator 参考&#xff1a;2021最新Qt6开发环境&#xff08;Qt Creator&#xff09;安装以及卸载记录_q…...

接口自动化yaml文件读取与写入

前言 在走进yaml文件之前大家应该都很想知道他是用来干嘛的&#xff1f; 是的是的&#xff0c;他是用来做接口自动化测试的。 我们一起来学习他吧&#xff01;——&#xff08;一定要收藏带走哦❤&#xff09; 1、yaml文件有什么作用呢&#xff1f; ①可作为配置文件使用—…...

Java Map、JSONObject、实体类互转

文章目录 前言Map、JSONObject、实体类互转 前言 使用库 com.alibaba.fastjson2&#xff0c;可完成大部分JSON转换操作。 详情参考文章: Java FASTJSON2 一个性能极致并且简单易用的JSON库 Map、JSONObject、实体类互转 import com.alibaba.fastjson2.JSON; import com.alib…...

在Hive/Spark上执行TPC-DS基准测试 (PARQUET格式)

在上一篇文章:《在Hive/Spark上运行执行TPC-DS基准测试 (ORC和TEXT格式)》中,我们介绍了如何使用 hive-testbench 在Hive/Spark上执行TPC-DS基准测试,同时也指出了该项目不支持parquet格式。 如果我们想要生成parquet格式的测试数据,就需要使用其他工具了。本文选择使用另…...

基于CentOS搭建私有仓库harbor

环境&#xff1a; 操作系统&#xff1a;CentOS Linux 7 (Core) 内核&#xff1a; Linux 3.10.0-1160.el7.x86_64 目录 安装搭建harbor &#xff08;1&#xff09;安装docker编排工具docker compose &#xff08;2&#xff09;下载Harbor 安装包 &#xff08;3&…...

PDF怎么转Word?8 个最佳 PDF 转 Word 转换器

PDF 转 Word 转换工具只是一个特殊程序&#xff0c;可以将 PDF&#xff08;本机和/或扫描&#xff09;转换为 Microsoft Office Word 格式。将 PDF 导出到 Word 的主要原因之一是满足可编辑文档的需求&#xff0c;尽管还有其他原因。 由于缺少 PDF 阅读器&#xff0c;您可以选…...

老板都爱看的财务数据分析报表,全在这了

老板们都爱看哪些财务数据分析报表&#xff1f;自然是可以帮助他们更好地了解公司的财务状况和经营绩效的那一类财务数据分析报表&#xff0c;比如利润表、资产负债表、现金流量表、应收账款分析报表、应付账款分析报表、库存分析报表等。奥威BI数据可视化工具有一套标准化财务…...

ZooKeeper(zk)与 Eureka 的区别及集群模式比较分析

​ 作者&#xff1a;zhaokk 推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 「java、python面试题」来自UC网盘app分享&#xff0c;打开手机app&#xff…...

搜狗拼音占用了VSCode及微信小程序开发者工具快捷键Ctrl + Shit + K 搜狗拼音截图快捷键

修改搜狗拼音的快捷键 右键--更多设置--属性设置--按键--系统功能快捷键--系统功能快捷键设置--取消Ctrl Shit K的勾选--勾选截屏并设置为Ctrl Shit A 微信开发者工具设置快捷键 右键--Command Palette--删除行 微信开发者工具快捷键 删除行&#xff1a;Ctrl Shit K 或…...

PMI-ACP值得考吗?在中国的前景如何?

相信很多小伙伴都听过PMP证书吧&#xff0c;但是对于PMI-ACP则知之甚少。那么同为项目管理证书&#xff0c;PMI-ACP认证的含金量怎么样呢&#xff1f;今天咱们就来聊一聊PMI-ACP敏捷项目管理证书。 PMI-ACP是由PMI&#xff08;美国项目管理协会&#xff09;颁发的针对敏捷项目…...

centos 安装防火墙,并开启对应端口号

1.查看防火墙状态&#xff1a; 命令&#xff1a;systemctl status firewalld.service 开启防火墙时&#xff0c;提示没有安装防火墙 [rootlocalhost ~]# systemctl start firewalld.service Failed to start firewalld.service: Unit not found.2.安装防火墙 [rootlocalhost …...

学习微信小程序时间延迟setTimeout和setInterval的使用方法

学习微信小程序时间延迟setTimeout和setInterval的使用方法 setTimeout()setInterval() setTimeout() setTimeout在使用的时候可以实现代码块延迟执行的效果&#xff0c;并且可以设置延迟执行的具体时间。请见如下代码&#xff1a; setTimeout(function() {//要实现延迟执行效…...

Vite好用的前端构建工具

是什么 Vite是Vue的作者尤雨溪开发的 一种新型前端构建工具。 Vite在大型项目开发模式下&#xff0c;打包速度远高于webpack。 Vite 为什么这么快 1. 快速冷启动 Vite只启动一台静态页面的服务器&#xff0c;不会打包全部项目文件代码&#xff0c;服务器根据客户端的请求加…...

Agile Iteration Velocity

【agile iteration velocity】敏捷速度指的平均速度 第四次迭代结束速度&#xff1a; 76 / 4 19 第五次迭代结束速度&#xff1a; &#xff08;76 24 &#xff09; / 5 100 / 5 20...

HarmonyOS/OpenHarmony应用开发-ArkTS语言渲染控制LazyForEach数据懒加载

LazyForEach从提供的数据源中按需迭代数据&#xff0c;并在每次迭代过程中创建相应的组件。当LazyForEach在滚动容器中使用了&#xff0c;框架会根据滚动容器可视区域按需创建组件&#xff0c;当组件划出可视区域外时&#xff0c;框架会进行组件销毁回收以降低内存占用。一、接…...

04_15页表缓存(TLB)和巨型页

前言 linux里面每个物理内存(RAM)页的一般大小都是4kb(32位就是4kb),为了使管理虚拟地址数变少 加快从虚拟地址到物理地址的映射 建议配值并使用HugePage巨型页特性 cpu和mmu和页表缓存(TLB)和cache和ram的关系 CPU看到的都是虚拟地址&#xff0c;需要经过MMU的转化&#xf…...

ResourceBundle类:读取配置文件

ResourceBundle类是java自带的类&#xff0c;类路径&#xff1a;java.util.ResourceBundle&#xff0c;用来读取项目中后缀为properties的配置文件。 下面简单举例说明一下用法&#xff1a; 数据准备 1&#xff09;配置文件名称&#xff1a;application.properties&#xff…...

数学建模的三大模型和十大常用算法

一、三大模型 预测模型 神经网络预测、灰色预测、拟合插值预测(线性回归)、时间序列预测、马尔科夫链预测、微分方程预测、Logistic模型等等。 应用领域&#xff1a;人口预测、水资源污染增长预测、病毒蔓延预测、竞赛获胜概率预测、月收入预测、销量预测、经济发展情况预测等在…...

NAS绝对安全吗?文件会不会泄露或被删除?

NAS&#xff08;Network Attached Storage&#xff09;并非绝对安全&#xff0c;因为任何系统都存在潜在的风险和漏洞。以下是一些可能导致文件泄露或被删除的情况&#xff1a; 1. 物理安全&#xff1a;如果未采取适当的物理安全措施&#xff0c;例如未将NAS设备放置在安全环境…...

Kubernetes 使用 Rancher 管理

K8S集群管理工具 只能管理单个K8S集群 kubectl命令行管理工具 dashboard&#xff08;K8S官方的UI界面图形化管理工具&#xff09; &#xff08;管理多集群很麻烦&#xff0c;切换不同集群每次需要更改kube-config文件[kubectl配置文件]&#xff0c;如果kubeadm部署每次都需…...

5G随身wifi如何选择?简单分类一下

最近5g随身wifi越来越多了&#xff0c;价格也一直走低&#xff0c;根据我的观察和总结&#xff0c;5g随身wifi可以分为这几档&#xff1a;&#xff08;普遍来说&#xff09; 1&#xff0c;紫光udx710基带芯片&#xff08;也叫v510&#xff09; 代表产品&#xff1a;r106&#x…...

华为PPPOE配置实验

华为PPPOE配置实验 网络拓扑图拓扑说明电信ISP设备配置用户拨号路由器配置查看是否拨上号是否看不懂&#xff1f; 看不懂就对了&#xff0c;只是记录一下命令。至于所有原理&#xff0c;等想写了再写 网络拓扑图 拓扑说明 用户路由器用于模拟家用拨号路由器&#xff0c;该设备…...

1.jvm和java体系结构

jvm简介 JVM&#xff1a;跨语言的平台 Java是目前应用最为广泛的软件开发平台之一。随着Java以及Java社区的不断壮大Java 也早已不再是简简单单的一门计算机语言了&#xff0c;它更是一个平台、一种文化、一个社区。 ● 作为一个平台&#xff0c;Java虚拟机扮演着举足轻重的…...

h264 SPS 帧分辨率解析标准

来源:微信公众号「编程学习基地」 文章目录 导致1088出现的原因h264 sps解析h264bitstream的简单使用导致1088出现的原因 大部分IPC推过来的数据流都是标准的1080P(1920x1080),720P(1280x720) 但是也有个例,部分设备存在16位/32位对齐的情况,出现非标1080P(1920x1088),72…...

二、SQL注入之联合查询

文章目录 1、SQL注入原理2、SQL注入的原因3、SQL注入的危害4、SQL注入基础4.1 MySQL相关4.2 SQL注入流程&#xff1a; 5、联合注入实例基本步骤6、总结 1、SQL注入原理 SQL注入(Sql Injection&#xff09;就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串&…...

Python爬虫入门 - 规则、框架和反爬策略解析

在当今信息爆炸的时代&#xff0c;爬虫技术成为了获取互联网数据的重要手段。对于初学者来说&#xff0c;掌握Python爬虫的规则、框架和反爬策略是迈向高效爬取的关键。本文将分享一些实用的经验和技巧&#xff0c;帮助你快速入门Python爬虫&#xff0c;并解析常见的反爬策略&a…...

【数据结构入门指南】二叉树

【数据结构入门指南】二叉树 一、二叉树的概念二、现实中的二叉树三、特殊的二叉树四、二叉树的性质五、二叉树的存储结构5.1 顺序结构5.2 链式结构 一、二叉树的概念 二叉树是一棵特殊的树。一棵二叉树是结点的一个有限集合&#xff0c;该节点&#xff1a; ①&#xff1a;或者…...

C++初阶——string(字符数组),跟C语言中的繁琐设计say goodbye

前言&#xff1a;在日常的程序设计中&#xff0c;我们会经常使用到字符串。比如一个人的身份证号&#xff0c;家庭住址等&#xff0c;只能用字符串表示。在C语言中&#xff0c;我们经常使用字符数组来存储字符串&#xff0c;但是某些场景(比如插入&#xff0c;删除)下操作起来很…...

Android Bitmap详解(下)之图片缓存详解

前言&#xff1a; 之前有出过俩篇关于bitmap相关的讲解&#xff0c;分别是Bitmap详解(上)常用概念和常用API和Bitmap详解(中)之像素级操作&#xff0c;今天主要是来一个系统的总结。 认识Bitmap&#xff1a; Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像…...

020-从零搭建微服务-认证中心(九)

写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&#xff1a;https://gitee.com/csps…...

孤注一掷中的黑客技术

最近孤注一掷电影很火&#xff0c;诈骗团伙的骗术实在厉害&#xff0c;就连电影中的黑客潘生都未能幸免。电影中的陆经理说&#xff1a;不是我们坏&#xff0c; 是他们贪。这句话我觉得有一部分是对的&#xff0c;诈骗分子抓住了人的本性贪婪&#xff0c;才使得被骗的人逐步走向…...

机器学习笔记 - PyTorch Image Models图像模型概览 (timm)

一、简述 PyTorch Image Models (timm)是一个用于最先进的图像分类的库,包含图像模型、优化器、调度器、增强等的集合;是比较热门的论文及代码库。 虽然越来越多的低代码和无代码解决方案可以轻松开始将深度学习应用于计算机视觉问题,但我们经常与希望寻求定制解决方案的客户…...

Java 实现证件照底图替换,Java 实现照片头像底图替换

效果图 这里前端用layui实现的案例截图 color底图颜色可以在网页上这样取色 new Color(34, 133, 255) 实现案例下载链接&#xff1a;https://download.csdn.net/download/weixin_43992507/88237432...

周易卦爻解读笔记——未济

第六十四卦未济 火水未济 离上坎下 未济卦由否卦所变&#xff0c;否卦六二与九五换位&#xff0c;象征尚未完成。 天地否 未济卦和既济卦既是错卦又是覆卦&#xff0c;这也是最后一卦&#xff0c;序卦传【物不可穷也&#xff0c;故受之以未济终焉】 未济卦象征尚未完成&…...

AI 绘画Stable Diffusion 研究(十三)SD数字人制作工具SadTlaker使用教程

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 想必大家经常看到&#xff0c;无论是在产品营销还是品牌推广时&#xff0c;很多人经常以数字人的方式来为自己创造财富。而市面上的数字人收费都比较昂贵&#xff0c;少则几…...

伦敦金走势图行情值得关注

不知道大家是否了解过伦敦金这个投资品种&#xff0c;或者有否财经网站以及金融终端上看到过它的行情走势图。其实&#xff0c;伦敦金并不是一种实实在在的黄金&#xff0c;而是一种跟踪伦敦现货黄金市场价格走势的黄金保证金交易品种&#xff0c;它每天的行情走势变化&#xf…...