9. kcp是如何榨干你的带宽的
KCP = 一种ARQ
老朋友了, 以前装梯子用过KCP-Tun
, 那时候只知道快但不知道为什么, 今天正好学习一下它. 首先什么是ARQ, ARQ是一种协议, 但在我看来更像是某种手段, 来保证包序, 以及包不会丢(稳定可靠性). TCP实现了ARQ, 因此TCP是可靠的:
TCP的停等ARQ模式: 一问一答的回合制模式
TCP的连续ARQ模式: 直接响应最后一个ack
KCP本身也是一种ARQ, 他自己实现了一套算法, 来保证包不会丢, 我这么说吧, KCP在TCP/UDP的上层, 他可以从二者中选择一个来包装一下, 传输数据的任务交给了TCP/UDP, 它自己只负责保证传输过程是可靠的.
但是TCP本身就有保证可靠的特点, 跟KCP的特性冲突了, 因此大部分时候我们选择KCP+UDP的组合, UDP负责传数据, KCP负责保证UDP的可靠性. 后面的文章中我们会看看KCP是如何保证可靠的同时, 做到"网络加速"的效果的.
RTO:Retransmission Timeout
RTO是指一个时长, 如果过了这个时长你还没收到响应, 就算超时, 那么想想也能知道如果两个节点相距很远, 一轮通信耗时(RTT)就会很长, 如果两个节点很近耗时就会很短, 这个RTO应该是动态计算出来的, 计算公式过于炸裂我就不看了. 关于RTO有两处可以做文章:
超过RTO,重发, 但如果这个包再丢了, 此时超时判断标准变成2*RT0, 想想如果这样下去第三轮丢包就是8倍RTO, 非常吓人
TCP为了不老发ACK(他认为会加重拥塞), 有一种Merge ACK的行为, 延迟200ms, 然后ack最后一个序号. 这种机制, 结合RTO的计算公式, 会造成RTO变大
以上两者都说明TCP存在着某种方式会让RTO变大, 而RTO如果变大了, 我们就需要更长的时间, 才能发现自己丢包了, 然后再重发, 这无疑就是在浪费时间, 针对这些行为, KCP的做法是RTO不会翻倍, 同样也不存在Merge ACK的行为, 所有这些做法都是为了降低RTO, 最快的发现自己丢包, 最快的重传
拥塞控制 = 浪费时间
我们在TCP的效率问题里提过, TCP的一个著名特点就是会做拥塞控制以及慢启动, 通过以下三者联合控制实际发包数量:
拥塞控制: 实际发包数量为
min(CongestionWindow,ReadWindow)
,慢启动: 在CWND小于
ssthresh
的时候翻倍, 大于ssthresh
的时候+1, 丢包则CWND减半.
但是慢启动, 思考一下, 我们可能需要很多轮, 才能到达最大吞吐量, 一轮是一个RTT, 很多轮就是很多RTT以后才能到达最大吞吐. 纯JB浪费时间, KCP取消了慢启动, 大部分时候直接按照最大吞吐量开始工作.
KCP就比TCP优越吗?
我们说了半天, 感觉很像TCP是老旧过时, 且慢的要死的方式, 是不是这样? 并不是, 二者的设计理念是不一样的.
TCP在丢包判断, 以及丢包处理上比较保守, 因此我们可以认为TCP是一个保守的协议, 它不过度抢占带宽资源, 它也不增加网络拥挤程度, 尽量给网络中其他机器一个和谐的环境. 与之相对的是KCP的激进态度, 用最短的时间, 判断出是否丢包, 并且发送最多的包. 这样的结果是如果网络真的拥塞了, 那么他这样会很严重的加重拥塞
Last updated
Was this helpful?