Kcptun: FEC问题讨论贴

Created on 21 May 2016  ·  94Comments  ·  Source: xtaci/kcptun

  1. 下载文件speedtest基本上下载2-3MB之后就会断开。
  2. 视频有时断有时不断,另外视频的status里面显示的connection speed也不正常,我只有10mbps的宽带,但是他能飙到60多k。
  3. 在视频播放视频的同时打开其他网站会很困难。

我之前用的版本印象中没有出现过以上问题,应该是 https://github.com/xtaci/kcptun/commit/a79537f9c6d959a107d1646fe338dff4d8bfd0dc 这个版本。

mode fast2
mtu 1464
mtu试过默认也没用
sndwnd和rcvwnd都是默认,服务端和客户端的版本、参数都是一样的
另外我是配合ss-libev一起用

下载断开时服务端的错误信息

2016/05/21 09:38:31 [ERR] yamux: Failed to read header: broken pipe
2016/05/21 09:38:31 broken pipe
2016/05/21 09:38:31 stream closed
2016/05/21 09:38:33 i/o timeout

下载断开时客户端的错误信息

2016/05/21 09:39:00 [ERR] yamux: keepalive failed: i/o deadline reached
2016/05/21 09:39:01 [ERR] yamux: Failed to read stream data: broken pipe
2016/05/21 09:39:01 [WARN] yamux: failed to send go away: session shutdown
enhancement

Most helpful comment

kcp协议本身的断线判断机制有问题,导致了在高速线路下会误判,出[yamux]broken pipe错误
现在是通过自己实现ping做链路断线判定。
另外适当调高了yamux的最大传输buffer,以适应高速传输。
减少了大量的内存分配。

All 94 comments

感谢,准备出门.晚上测试!

PS. 楼主把 mtu 改小为 1300 测试下.看还会不会有断开的情况.

另外解释下 -fec的意思 -fec N表示每N个包发一个纠错包,比如 -fec 4,那么纠错包占用 1/(1+4) = 20%的传输量。 -fec 0 表示关闭fec包

mtu改为1300也会断,1464是我试出来的可以用的最高的,1465就明显不稳定速度慢了

加了--fec 0还是会断,效果就和没关一样

@xtaci 我试了一下 fec 的最新 build:

  • 如果是小流量,比如 ssh, 那么一直使用着都没问题
  • 如果是高流量,比如 curl 下载 digital ocean 的 speedtest (速度 1MB/s 左右, 系统显示 2.5MB/s), 那么下载 10MB 左右的数据量的时候,就会报错
2016/05/21 11:46:25 [ERR] yamux: keepalive failed: i/o deadline reached
2016/05/21 11:46:26 [ERR] yamux: Failed to read stream data: broken pipe
2016/05/21 11:46:26 [WARN] yamux: failed to send go away: session shutdown
  • 另外还发现,如果我下载 digital ocean 的 speedtest, 即使还没有报错,我按 ctrl-c 把 curl 停掉,然后再次下载,就连不上了。诡异的是, 我发现这时尽管已经没有在下载了, 但系统的实时流量仍然显示 2MB/s 。

me too

2016/05/21 13:39:20 [ERR] yamux: keepalive failed: i/o deadline reached
2016/05/21 13:39:20 [ERR] yamux: Failed to read header: broken pipe
2016/05/21 13:39:20 stream closed
2016/05/21 13:39:20 stream closed
2016/05/21 13:39:20 stream closed
2016/05/21 13:39:20 stream closed
2016/05/21 13:39:20 stream closed
2016/05/21 13:39:20 session shutdown
2016/05/21 13:39:20 communication mode: fast

release和降低sndwnd/rcvwnd都试过了,还是不行,挺奇怪的
我之前go get的版本一切都正常,我服务器用的budgetvm,丢包少,用老版本没怎么断过

我发现这时尽管已经没有在下载了, 但系统的实时流量仍然显示 2MB/s 。

试了下,这个问题不管是否打开 fec 都存在。但是用 5 月 8 号的版本是没问题的。

可以试下最新的build ,内容已经重新upload,可能是这个问题,因为我这里没有重现,也不能100%确定

试了最新的 release (linux server + mac client), 还是一样的情况

另外尽管两边都打印 "stream closed", 服务器和客户端都显示仍然在传输数据。

OK, 继续review

@lins05 再重新下载试一下,我调整了一个kcptun的参数。

最新版本 yamux 出错的消息已经没有了,赞!不过我这里仍然有 "下载中断后服务器和客户端都仍然在传输数据" 的问题。我试了下用两台 AWS 机器,一台做 server 一台做 client, 就没有这个问题。

另外,推荐端口 rtsp/554, mms/1755 貌似电信干扰较少

嗯,没有严重问题就好,代码还需要review

Video ID:fdXvWa52nnY
Dimensions:854 x 480 * 2
Resolution:854 x 480@25
Volume:100%
Stream Host:r3---sn-ogueln7d
Stream Type:https
CPN:R16U1ASJMZ_o3wQw
Mime Type:video/webm; codecs="vp9"
DASH:yes (244/251)
Connection Speed:6553 Kbps
Buffer Health:357.4 s
Dropped Frames:

平均速度能到6553Kbps, 最高超过8000Kbps

keepalive timeout的问题,我感觉是yamux的flow control不够均匀引起的。

更新了一下,路由器需要保持NAT ,ping间隔不能太短。

我试过 18 和 21 两天的 build,但在我的环境中都更快地出现了 TX/RX 为 0 的情况(客户端为 RPI)。所以我现在回到了 17 日的 build (就是那个被删掉的版本)。

@xtaci 我发现 10几号之后的版本都会存在 "下载中断后服务器和客户端都仍然在传输数据" 的问题,所以回退到了 5 月 7 号的版本。这个版本比较稳定,现在的 master 版本不管是否打开 FEC 都不稳定。

@yaleh @lins05 我查了下,18好的改动就是及时发送ACK,这样确实会导致上行数据包增多,可能是导致问题的原因,另外,下载中断后服务器和客户端都仍然在传输数据的问题,可能也是因为18号左右的调整。 我重新发一个版本,回退到17号的延迟ACK,并且yamux的窗口降低。

@yaleh @lins05 再麻烦测试一下

我在speedtest.net的结果是
12.95Mbps下行 11.44Mbps上行

@xtaci 试了下,确实修复了 "下载中断后服务器和客户端都仍然在传输数据的问题",赞!

另外稳定性好像也和 之前的版本一样了,不过不知道是不是因为这个点网络比较好的原因。

@lins05 希望就是因为这个原因哈,明天再试试,你们给出的线索很重要!

根本原因是kcp-go的Write没有实现阻塞的语义,导致的中断后数据传输的问题,后面会想办法实现阻塞语义。另外的一个优化方向是降低头部的overhead开销,增大数据的payload载荷以提高速度。

另外我建议应该在两边都加一个计数器,以及一个 --debug flag,debug 打开的情况下,在 stdout 隔几秒打印一下 FEC 纠正了多少丢包错误,不然很难观察到 FEC 的效果。

是的,统计会加的,工作量比较大,会比较靠后,最终效果会类似netstat -s
或者 /proc/net/snmp

恩,理解,不过我倒觉得可以考虑提高优先级,毕竟做性能优化的时候都说 "measure twice, cut once"

嗯,尽量吧,基本想法是

struct {
      retrans int64
      fec_recover int64
      bytes_sent
      bytes_received
      ...
      num_rto
      repeated 
}

20160522 与 20160517 的表现相当,我现在已经在用了。不过也没体现出 FEC 的优势。

在我的电信到日本线路上(客户端为 RPI ),比较好的参数是:

-e 'SNDWND=2048' -e 'RCVWND=256'

Server/Client 均使用以上参数,kcp 吞吐量 5MBps 上下,有效载荷 1MBps 左右,未出现 TX/RX 为零情况。

@xtaci 好像比昨天的版本快了不少,做了什么调整吗?

kcp协议本身的断线判断机制有问题,导致了在高速线路下会误判,出[yamux]broken pipe错误
现在是通过自己实现ping做链路断线判定。
另外适当调高了yamux的最大传输buffer,以适应高速传输。
减少了大量的内存分配。

@xtaci 另外我这里单个 kcp client 下载,不管服务器的 sndwnd 和本地的 rcvwnd 怎么设置,有效下载速度最大只能到 1MB。但是同时启动三个 kcp client 的话, 每个都能到 800KB 左右。

@lins05 这个就是interval的问题,20ms等待期间啥都干不了,多个client能利用这些时间

@xtaci releases里面的还是以前的版本吧

@lp123sun 最新的

Video ID:-hIugp7p5O0
Dimensions:1280 x 720
Resolution:1280 x 720@25
Volume:100%
Stream Host:r1---sn-oguesnz6
Stream Type:https
CPN:BVHobwVYIRwJlNrl
Mime Type:video/webm; codecs="vp9"
DASH:yes (247/251)
Connection Speed:7045 Kbps
Buffer Health:305.4 s

connection speed逐渐提高到7045 Kbps

详细跟踪了今天的修改,感觉改进得不只有一点啊.现在马上测试!

关于断线判断,我自己都是自己在会话层来做断线判断的,你可以发现kcp的deadlink这个数值只是个给外面的参考,KCP协议内部基本没有用到 deadlink这个结果。即便你deadlink=1了,整个协议照样可以工作。

嗯,今天在transport层实现了ping,彻底没有用deadlink做判定了,以前即使设置到50次xmit,在高速网络下也有可能断掉,很不爽,今天改成ping了。:smile:

恩,我自己也是外部检测,另,Go的udp是否可以设置TOS标志?根据cisco的说法,默认的数据包优先级都是“尽力服务”,就是中间网络节点尽可能的提供传送服务,设置TOS后,兼容cisco标准的设备上就能获得了仅次于“网络控制信令”的优先级,使得对应数据包在网络各个节点上能够得到最优先的处理。

@skywind3000 现在的整体感觉是,再往上提高一点速度,非常难。
我能想到的原因是,ADSL 上行的包/带宽,限定了ACK的最大速度,如果改成input后及时flush ack出去,速度反而更慢,可能是路由器开始丢包。

现在的策略是,Write()是及时flush(), ACK 是最大延迟10ms发送,这样能得出一个比较满意的速度。

TOS都能设置的,提供了所有的Syscall, 我试试,如果设置tos不要求root权限就直接加上去。

最新一版好猛啊,fast2模式走垃圾线路到美国都能满速。

@xtaci
我测试了 azure 的日本区 100M 的测速文件下载, 总体速度增加 1.5 倍左右.

ytb 速度提升得更明显,特别是视频刚打开的时候,一度增加到 10Mb/s 小b. 不过持续8s 左右就会下降.目前视频偶尔的画面质量选择会在 1080p 的画面质量.总体现在的版本我觉得是非常给力的.

感谢啊,大神,太给力了!

@jannson 昨天的release版本有一个小小的安全隐患,已经fix了,另外换用了crc32替换md5。
FEC版本到此算基本稳定了。

收到。昨晚用上瘾了,看视频到半夜两点,期间选很多个高清视频看,基本稳定,就偶尔极少情况会小卡一会。
ytb 播放速度会在 5Mb/s ~ 11Mb/s 之前。测试期间全程放在路由器里运行,透明代理。感觉放在路由器里运行有速度更快的错觉。

感觉马上可以正式 release 一个版本了。

@jannson release稍等一下,今天把TOS加上后,就算完备了。 立即发布。

@jannson 已经发布带TOS的版本,如果没有明显的BUG,就算定版了。

期待宝大的梅林版。

@jannson 路由器更快不是错觉,某些路由器对udp包很不友好,经常丢弃,直接刷自己的固件就没有这个问题了。 :bowtie: 另外,TOS这个设置我觉得才是玄学,只能凭感觉哈,我感觉传输稳定不少。

@appleatiger 别在这里这么叫我,我是 @xtaci 的粉丝了。天天当小白用户测试半小时以上。

目前23 24两个版本在同一个IDC商,两台不同的VM上在同时在测试。目前第一印象24版相对于23版有些微小的速度差异,23版更快速。

全程平均延迟大约差14%左右,同样的IDC,同样的线路,同样的客户机,同样的数据流,以上。

@jannson TOS设置有点问题,更新了

@appleatiger 试下最新的release,加上了TOS设定的。
另外,延迟和吞吐不可兼得。

开始测试13:36分的版本

@appleatiger 我几分钟前才上传的,直接覆盖的0524版本。

测试结果是23日版本的最大吞吐,全过程延迟好于最新版本,最新版本的上传数据比23日版本少50%

@appleatiger 24 的改动非常小,不会有这么大的差别, 另外,上行带宽形态很难琢磨,建议测试下行带宽。
24日的改动:

  1. 头部magic number 从23日的4B还原为12B, 除非读取随机数卡住才可能降速
  2. 头部的MD5替换为CRC32, 这个是提速,明显计算会变快
  3. 设置了TOS

技术我就不懂了额,测试时,是对同一个视频的多种清晰度的播放及对同样的多个网站依次的多次打开20秒后再关闭。版本是23日版本与最新13:36分版本的对比。数据上就是上面讲的。为减少负载干扰,两台服务器是同机房的,并且都仅安装了ubuntu14.04,ssr及kcp,没有其他负载,两台客户机接在同一局域网的同一级交换机上。客户机型号相同的两台笔记本,均为最新win10系统。唯一的区别可能是ssr的服务端版本有差异。不过ssr仅仅是作为本地转换,差别不会这么大吧。

@appleatiger 干扰尽量排除吧, 因为我用24日的版本,是非常流畅的,和昨日的版本几乎完全一样。
如果真的有差别, 那么只可能是头部增加的12个字节的随机数导致的。但这个不可能啊。

我再在实际使用过程中体会吧,短期数据和长期体验可能并不相同,明天再来汇报。

最新版感觉很稳定啊,加FEC之前的版本虽然下载和视频不会断,但是跑speedtest.net会断,新版跑speedtest.net也没问题了,更完美了。
现在就感觉还有一个问题,比如浏览器和一个ssh同时经过kcptun,浏览器下载文件,这时候在ssh里打字就会很卡,这是加FEC之前的版本没有的。
如果是浏览器一边下载文件一边再开新的网页也会感觉比FEC以前的版本慢些,不过没有ssh那么难受就是了,稳定就好。

@ekkolord 实时性和吞吐量,不可兼得

@xtaci 最新版本确实速度不错,稳定性也不比之前的差,赞!

不过还是有之前 “单个 kcp client 下载,不管服务器的 sndwnd 和本地的 rcvwnd 怎么设置,有效下载速度最大只能到 1MB。但是同时启动三个 kcp client 的话, 每个都能到 800KB 左右” 的问题。

@lins05 这个问题相当复杂了 可以把服务器和本地,的所有sndwnd/rcvwnd全部调大再试试

@lins05 我放个选项出来,可以手动开启,可以试试

@lins05 试试这个选项

  1. Optional -noackdelay option, enable it to flush ack immediately.
    你可以选择双边或单边开启

@xtaci 试过了,调整 sndwnd/rcvwnd ,以及双边或者单边开 -acknodelay 都没什么区别

@lins05 这个问题只有持续观察了

恩,现在这样挺好用了,感谢你持续的改进,辛苦!

嗯,最近改动确实比较密集,后面稍微放慢点节奏了。

昨晚测试,看了一个小时左右视频,效果与前天晚上无区别。 或者有可能慢一点点。因为没有飙升到 11Mb/s 的机会了。最大也只到 8Mb/s

刚才试了下-acknodelay 貌似比不开要快些,实际区别不是太大视频基本稳定在13mpbs左右,高的时候会有17mbps

TOS选项我做个开关,可能对带宽不一定是完全无副作用的

@jannson @lins05 @wxyzh @ekkolord
0525的版本已经放出,主要是把tos(dscp)字段放出来了,根据可靠专业通信人士的建议,改为可选项。
DSCP的设定,可以参考 https://en.wikipedia.org/wiki/Differentiated_services#Commonly_used_DSCP_values

另外,速度问题,可以对比下fast/fast2

这个 dscp 就是给 ip 包做分类的意思吧,实现优先级?

某些主干网络的交换设备能识别此字段,从而给予数据包较高的传输优先级

@jannson @lins05 @wxyzh @ekkolord 麻烦测试一下0524的版本

数据发送问题,之前并没有及时发送(延迟了10ms),已经修正。可能涉及到@lins05说的吞吐问题

在 el capitan 里面 dscp 的设置没用,set tos: setsockopt: invalid argument

@trivita mac os 不支持设置tos,我也设置不了

@trivita 不会哈,肯定行,我刚试了,设置不成功dscp不影响运行,我能想到的不能建立连接的原因有:

  1. 双方-key不一致
  2. 双方-fec 不一致
  3. 端口无法通信

默认就是46吧,设成其他的会有影响吗,https://www.tucny.com/Home/dscp-tos 看了下,按照优先级也就40 ,44,46,48,56的优先级高些。待会试试fast2的

有影响,我咨询过专业人士,最好还是设置为0,TOS的有效性取决于ISP的策略,这个策略还是动态的,较难琢磨。

我相信专业人士,不过可惜 mac 啥也干不了,所以上行包就没辙了

感觉还是wnd有意义,clinet设成了1024,1024 5个做负载 视频在15mbps左右。现在dscp设成0了

@wxyzh 本地 haproxy,远程5个server?

差不多,vps上一个ss-libev,本地haproxy带5个kcptun

@wxyzh 本地带 5 个 kcptun,速度上会有提升么?提升多少?
这个我倒是没有测试过。

-dscp 46 我测试的结果是 client开比较好,服务器还是保持 -dscp 0,ISP的QoS能较好的适应 ,换句话说,就是mac用户无法享受dscp带来的好处(mac无法设置dscp)

@jannson 这个估计和网络环境有关系,我用iperf测试加不加kcptun的区别不是太大。远远没有达到本地和vps的最大带宽,没用kcptun时 youtube的速度只有5mbps左右。

效果比较好的配置参数为:

CLIENT:
-rcvwnd 2048 -sndwnd 256 -dscp 0 -mtu 1000

SERVER: 
-sndwnd 2048 -rcvwnd 2048 -dscp 0 -mtu 1000 -acknodelay

2Mbps上/32Mbps下

Was this page helpful?
0 / 5 - 0 ratings