xtaci / kcptun

A Quantum-Safe Secure Tunnel based on QPP, KCP, FEC, and N:M multiplexing.
MIT License
13.93k stars 2.54k forks source link

希望增加SNMP信息实时写入指定文件的功能,以方便调试参数。 #342

Closed bettermanbao closed 7 years ago

bettermanbao commented 7 years ago

或者增加控制台关闭log,然后实时显示的SNMP参数功能。

谢谢!

bettermanbao commented 7 years ago

nodelay=0的多等一下,具体是多等多久呢?

xtaci commented 7 years ago

多等 1/8 RTT

bettermanbao commented 7 years ago

测试了一天,挺好用的,发个release吧。

xtaci commented 7 years ago

多测试一下, 等你出个图

bettermanbao commented 7 years ago

今天测了各种参数组合,也不记得那个时间点用的是哪组参数了。 明天集中测试一下normal,fast,fast2,fast3这4组默认参数的表现吧。

xtaci commented 7 years ago

嗯,很好的开始,influxdb可以分析这类时序数据并grafana可视化,机器学习也可以用了。

bettermanbao commented 7 years ago

你走得太高端了。。。 继续测试RepeatSegs,下图是RepeatSegs/InSegs的比例,数据是youtube开着某1080p视频时在客户端采样的。 简单的结论,在我的网络中fast mode相比fast2 mode,由于多等1/8 RTT,可以有效降低服务器端因为误判导致的重复发包,并且承载速度明显提高,说明多等的这些时间确实等来了ack包。

fastvsfast2

dearneo commented 7 years ago

赞一下两位大神,加大interval参数的方式可以减少重复包的发送,应该就是变相的指定多等一下ack包咯?速度变慢的问题,我简单粗暴地把发送窗口加大。。。

我测试的方式简单粗暴,直接用windows客户端kcptun-gui开流量统计 kcp 实测客户端只有kcp流量为1.1~1.2倍的原始流量,但出站流量不知怎么基本都在8倍以上

bettermanbao commented 7 years ago

相同窗口下,加大interval,会导致速度变慢。这个现象我也观察到了,@xtaci 能否专业的解释下interval参数的工作原理?谢谢!

xtaci commented 7 years ago

interval 就是控制kcp的flush的间隔的的。所有的重发/发送逻辑都经过interval后触发

bettermanbao commented 7 years ago

那重发的内容是否会因为interval变大,有些原本没到的包,晚到了,而不重发。 还是说是否重发只是由nodelay和resend参数控制的?

xtaci commented 7 years ago

fast resend的逻辑我觉得有点问题,应该加入一定的delay,举例:

resend :2 数据包到达序列:

1,2 , [3]丢失 ,4 ,5 (到达第一个interval,flush第3号包) ,7,8... 100 (到达第二个interval,再次flush第3号包)

在这个过程中, 3号包在很短的两个interval,假如单次是10ms,发送了两次, 如果RTT本身是300ms, 抖动50ms, 那么很可能3号包会发送5次。不仅如此,在主动Send的时候,如果立即flush,会更多次的发送3号包。

@skywind3000

这个问题能不能分析一下?

xtaci commented 7 years ago
8f847c80-8956-4405-a0e2-1cb07bf67f7f

@skywind3000, fastresend也应该经过rtt才需要触发吧。

xtaci commented 7 years ago

@bettermanbao 麻烦重新编译下最新的kcp-go, 我更改了部分重传参数 ,测试一下。 这个是否和repeatSegs过高有关系,比较怀疑。

bettermanbao commented 7 years ago

好的,我刚才研究了一下,因为没读过代码,以下解读全凭猜的。

nodelay 是控制超时重传的时候是否再多等一会。 inteval 是超时重传的间隔,和下面的resend控制的快速重传没有关系。 resend 只是控制快速重传,超过resend间隔没收到的包会立刻重传,无需等到inteval到了再发送。 nc 比较复杂还没研究透。

然后我试下来,0 300 0 1的参数,RepeatSegs明显降低。

xtaci commented 7 years ago

对,如果interval和repeat有关,那么fastresend是最大的嫌疑,因为就这个不受时间控制。

baggiogogo commented 7 years ago

default 2

长时间都在routeros里观察 nodelay这个参数俺一直都是关闭的,感觉太激进,时常突破窗口设置阈值。 interval估计和设计初衷有关,(流速、流量),另一个帖子网友也提过这个问题,就是过大的interval会造成传输曲线不稳,这在routeros里看的也很清楚,例如20M的阈值,那么可能5M、10M、20M这样跳,而小的interval则一直压着阈值上限走,感觉像是单次的传输VS多次传输。 最后还有个问题一直都没人提过,如果同时尝试下载和youtube,不用多长时间一定爆表,幅度还挺大,这个和缓冲大小有关吗?

bettermanbao commented 7 years ago

看了server端和client端同一个时间点的snmp log,此时是在下载,所以数据是从server端发往client端。 client端收到大量RepeatSegs时,server端会出现大量LostSegs导致的重传,时间点完全吻合。

希望这些数据对分析有用。

client server

xtaci commented 7 years ago

@bettermanbao 这个是最新的kcp-go么? 我刚刚提交了一个改动。

bettermanbao commented 7 years ago

以上数据,就是用更新后的kcp-go收集到的,看来这个更新无用。 现在问题是kcp-go在发送数据时,是怎么判断lostseg的?等待多久没收到ack就算lost?

xtaci commented 7 years ago

我觉得这个数据挺好的,误判率不高。 我在这里测试效果还挺好的。

xtaci commented 7 years ago

另外,不要想着完全消除repeat, 不可能的哈。误判率平均10%已经不错了

bettermanbao commented 7 years ago

既然有数据了,就可以想办法优化。 继续回到我的问题: 请问kcp-go在发送数据时,是怎么判断lostseg的?等待多久没收到ack就算lost?

bettermanbao commented 7 years ago

把client端的repeatseg 和 server端的lostseg画成图,吻合度非常好。 如果是50%的误判,也许无能为力,但是这个是100%的误判呢,应该有办法在软件层面降低吧?

repeatvslost

xtaci commented 7 years ago

这个不叫100%误判, 这个就相当于每个数据包多发了一次而已。

bettermanbao commented 7 years ago

每个判断丢包重发的包,在接收端看来都是没必要重发的,这不就是100%误判嘛。

其实我关心的是发送端对于丢包的判断能否再宽容一些?因为从数据看来,现在是有些严格了。

xtaci commented 7 years ago
803     atomic.AddUint64(&DefaultSnmp.RetransSegs, lostSegs+fastRetransSegs+earlyRetransSegs)
804     atomic.AddUint64(&DefaultSnmp.LostSegs, lostSegs)
805     atomic.AddUint64(&DefaultSnmp.EarlyRetransSegs, earlyRetransSegs)
806     atomic.AddUint64(&DefaultSnmp.FastRetransSegs, fastRetransSegs)

以上是全部的retrans segs

losts只是 retrans的一部分。

bettermanbao commented 7 years ago

但是从我的数据看,所有retranssegs中,lostsegs是占比最大的,并且时间上和接收端的repeatsegs吻合。所以我才觉得这部分应该是可以优化的。lostsegs的判断应该超时即认为是丢包,那这个超时是怎么设置的?是否就是interval?代码不懂呢,求大神指点。

xtaci commented 7 years ago

超时是根据RTT + 抖动 计算出来的, TCP/IP详解卷一中文版,第232页。

这就是那个 “调得一手好参数”的故事

bettermanbao commented 7 years ago

kcp.go中 if kcp.nodelay == 0 { segment.rto += kcp.rx_rto } else { segment.rto += kcp.rx_rto / 2 } segment.resendts = current + segment.rto lost = true lostSegs++

请问以上这段代码中的segment.rto += kcp.rx_rto如果改成segment.rto += kcp.rx_rto * 2,应该能够明显降低lostseg的比例吧?

xtaci commented 7 years ago

当然 速度也会慢

xtaci commented 7 years ago

@bettermanbao release发了

bettermanbao commented 7 years ago

嗯,谢谢。我还是会试试rto*2的结果。

dfdragon commented 7 years ago

"你不指定日期就不新建了 -snmplog /xxxx.csv 即可"

测试的时候图省事,随手指定了一个文件名1.csv,结果生成的文件名是12.csv,抓了半天脑袋才发现是time.Now().Format闹的,本月是12月

bettermanbao commented 7 years ago

上几张图片,主要分析的是客户端的数据。 间隔1分钟采样一次,mode fast,FEC(30,10)。 RepeatRatio = RepeatSegs/InSegs,服务器端因为误判造成重复发包的比率。 FECRatio = FECRecovered/FECSegs,FEC恢复的效率。 kcptun_snmp

xtaci commented 7 years ago

牛逼啊,很有意思。

bettermanbao commented 7 years ago

顺便确认一下,FEC恢复的包,接收端也是会回发一个ack的对吗?@xtaci

xtaci commented 7 years ago

嗯,看了下现有逻辑, kcp.go第546行 在窗口范围内,重复的包会发重复的ack, 但是kcp.go第638行,会再此检查窗口,窗口外的ack剔除了。

xtaci commented 7 years ago

嗯,这里的逻辑我觉得可能有改善的地方。

bettermanbao commented 7 years ago

重复接收到的包,应该是始终回复ack吧?发送端就是因为没有收到之前的ack,才重复发送。重复的包如果不回复ack,那发送端不是一直不知道接收端包已收到了吗?

还有,FEC恢复出来的包,也应该是始终回复ack的。因为恢复出来,和实际收到其实是一样的效果。

xtaci commented 7 years ago

是ack + una两者判定的。 una + rcv_wnd范围内,是client发送过来的una,已经确认了的范围,所以低于这个范围内的ack,不需要ack.

这是合理的逻辑,不是始终需要ack窗口外的包。

第二个问题是,窗口内,并且在interval内的, 一个是正常push的ack,一个是recovered的ack,需不需要发送两份。

bettermanbao commented 7 years ago

我不是很懂,请教una指的是?

xtaci commented 7 years ago

假如una = 0 , rcv_wnd = 1024 那么, [0, 1024] 就是发送端所有可能发送的数据包的范围。

xtaci commented 7 years ago

也应该没什么可以改动的。

bettermanbao commented 7 years ago

那接收端通过FEC恢复出来的包,发送端是否仍然有可能重复发送?

xtaci commented 7 years ago

有可能的,假如 fec(10, 3) 那么我先收到9个包,客户端什么都不发送了, 等了几秒,这个时候,超时重传第10个包,凑够10个包,可以发送FEC的后面3个包了。 这个时候recovered出来的,必定重复。

bettermanbao commented 7 years ago

不是很理解,发送端应该是13个包一组,13个包一组发送的。 第10个包如果超时,11-13假设先到达。这样FEC就能直接恢复第10个包,对于kcp层就是10个包全部收到。然后10个ack一起回发。是这样吗?

xtaci commented 7 years ago

问题是,交互式应用,比如我每5秒发送一个应用层的请求,128个字节。 短时间内根本凑不够fec的datashard个数啊

bettermanbao commented 7 years ago

这个另当别论,我说的是比如大流量下载时。 发送端应该是13个包一组发包。 第10个包如果丢包,11-13假设先到达。这样FEC就能直接恢复第10个包,对于kcp层就是10个包全部收到。然后这10个ack都会一起回发,告诉发送端你发的10个包我都收到了。是这样吗?

xtaci commented 7 years ago

不是,不会等到13个包一组发,而是来一个发一个,凑够10个,立即发送3个parity