FULI
FULI
流量整形后,发送端的某个流不会霸占整个带宽,发送带宽竞争更加公平。 这样产生的效果是,对某个流量高的stream,产生了write()阻塞,阻塞会反馈到发送源头,通过拥塞控制的传导,使其发送速度减慢。 当然,这个减慢是在窗口(带宽)满了后的行为,窗口不满的时候不会产生。 https://github.com/xtaci/kcptun/releases/tag/v20190910
你的rcvwnd太大,因为很可能rcvwnd已经超过线路最大带宽,那么物理上的拥塞一直没有反馈到逻辑的拥塞上,无法触发shaper逻辑。你观测到的阻塞,很可能只是因为线路的阻塞。 注意,这个改动的假设是,**滑动窗口满后**,smux会均匀发送各个流的数据。如果线路没有拥塞,那么是FIFO的情况。
```go // shaper shapes the sending sequence among streams func (s *Session) shaperLoop() { var reqs shaperHeap var next writeRequest var chWrite chan writeRequest for { if len(reqs) > 0...
如果只管发送,不管读取,那么操作系统的 TCP socket buffer(net.ipv4.tcp_rmem),一样也会塞满,占用内存,这样的链接多了后,OS是分配不出来内存的,也会导致新的链接速度降到很低(rcv_wnd变小)。 可以理解为,操作系统的内存够大,在大多数时候避免了出现HOLB的问题,那么问题等价于提高`-smuxbuf`的数值,也可以在大多数时候避免出现HOLB问题。 目前唯一缺乏的,是tcp per socket buffer的设置,即per stream buffer的设置。 要实现这个,就需要扩展smux,增加控制指令,告知发送方当前的stream buffer的大小。
https://github.com/xtaci/smux/tree/v2 可以看下这个分支 smux v2协议升级,可以实现per stream的流控,理论上可以解决这个阻塞问题。 增加协议 `frame.go: cmdUPD`
但注意,虽然smux version 2.0可以缓解HOLB问题,但依然受制于 **有限的内存,并行,充分的带宽利用,三者不可兼得** 困境。 1. 当 streambuf = smuxbuf的时候,等价于smux version 1 2. 当streambuf < smuxbuf时,在限定了stream内存使用的同时,stream带宽也就被限定了。 3. 同时提高streambuf和smuxbuf,可以通过牺牲内存的来获得最大带宽。
我放了个pre-release https://github.com/xtaci/kcptun/releases/tag/v20190922 可以先尝试下这个版本,设置如下: ``` -smuxver 2 -streambuf 1048576
目前我认为这是唯一正确的办法, 即:实现对发送方Write()函数的阻塞控制,流式的窗口滑动。
已经放入 https://github.com/xtaci/kcptun/releases/tag/v20190923
you can also disable FEC by setting `-ps 0`