Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

未来是否考虑:支持多物理传输层,聚合加速 的功能 #2082

Closed
hedahong opened this issue Dec 5, 2019 · 25 comments
Closed
Labels

Comments

@hedahong
Copy link

hedahong commented Dec 5, 2019

我看到 4.3之后的版本中 ,可以通过在 routing 中配置一个 balancers 的方式,实现出站的负载均衡的效果,我认为这是在宏观上缓解整体出站的压力,比如a,b,c 三个出站通道,随机选择一个 为应用层连接提供 协议+传输 服务,从某个应用层(客户端)的视角来看,只是实现了出站abc仨选一的效果,abc三个通道的效果决定了用户体验。

需求:
我希望在出口传输层,能支持多物理传输层通道 聚合加速(带宽叠加) 的效果,比如说我有个移动的主机(路由器大小的盒子,带WIFI),上面插了6张4g上网卡,但每张上网卡的出站只有100Kbps,我的应用层需要 300Kbps才能工作(比如 户外直播推流,AR等应用),按路由器做透明代理的思路,对应用层Wifi 透明接入,底层多通道 聚合加速,完美。

@kslr
Copy link
Contributor

kslr commented Dec 5, 2019

没有这方面计划,第三方软件比如haproxy来做这些事情更专业

@hedahong
Copy link
Author

hedahong commented Dec 5, 2019

haproxy 不具备这样的能力,她就是个HA

@kslr
Copy link
Contributor

kslr commented Dec 5, 2019

这不在目标之中,但如果你有兴趣也可以来做这方面的事情

@hedahong
Copy link
Author

hedahong commented Dec 5, 2019

好的,谢谢,我感觉可能要从 KCP 或 QUIC 之类的传输层 思考。

@kslr
Copy link
Contributor

kslr commented Dec 6, 2019

最快的办法就是叠加你的网卡

@tanyiok1234
Copy link

聚合加速是很难的,因为实时检测各个传输链路的性能并不容易,暴力的冗余发包会降低实际带宽,而不正确的链路检测会导致延迟/带宽偏低。
我猜他的意思可能是,即便只有一个物理链路,不同的传输协议(UDP/TCP)在ISP侧的限速策略不同,因此总的QoS限制带宽可能比单一传输协议要大。因此理论上(可能)可以提升速度。不过其实收益不会很高啦。
实际上我以前认真想过这个问题,要实现这个功能,最方便的方法是在(v2ray)协议层的输入和输出层之间插一层虚拟层,使客户端的输入协议(服务端的输出协议)看到的是一个理想的可靠传输信道。而虚拟层将协议层的流式传输连接重新封成新的连接并放进不同的传输层传输。这样对程序的改动应该是比较小的,只要添加一个可以当传输层协议也可以当传出传入协议的新模块。
问题是,如此改动,实际收益实在堪忧,吃满单个传输链路带宽情况实在太少了。瞬发带宽更多的取决于类似BBR之类的发包算法,而(TCP/UDP)同时发包也许反而干扰算法收敛。我觉得唯一的收益大概就是当低延迟的quic低QoS带宽饱和时自动切换TCP让人实现自适应高带宽/低延迟切换罢了(比如突然从看小说改成看高清漫画)。又或者让应用层看到NAT超时变得超长(emmm...但是未必就省电了)。
总之,好处有限,比起工作量实在是有点。。。。可能等quic-go实现了链接迁移之后我就有动力研究了吧(咕咕咕

@ailinwang
Copy link

V2RAY工作在运输层,我觉得下层要是涉及良好的话应该让细节对上层透明,不然V2ray的结构会过分复杂,导致维护困难的同时带来更多特征点和漏洞。

@gxlzlu
Copy link

gxlzlu commented Jun 28, 2020

好处还是有的,尤其对“懒人”。比如,现在都是“机场”模式来科学上网,机场会分配多个节点。那么某个节点被墙了之后,其余节点还能通,在链路聚合之下,就不用重新配置哪个节点可用了。否则就是,哪个节点被墙了,就要重新配置一下服务器。
期待链路聚合功能的实现呀!

@genufish
Copy link

genufish commented Jul 7, 2020

你的想法需要服务器端支持。。。基于数据流的负载均衡是选择最优链路/服务器进行数据流传输,传输过程和正常代理没什么差别。基于数据包的聚合加速将数据包在各个链路上同时传送到服务器,然后由服务器重新组合。如果真想做的话,把代理出口传输设成quic,然后把udp包通过不同socks代理发出,在服务器端收到udp包后重组数据流。负载的话可以按最近传输的数据量比例分配,但肯定需要服务器配合重组数据流。用可靠udp协议分流的好处:一,不用考虑各个链路速度差异导致数据到达顺序问题;二,不用考虑单个链路故障导致的部分数据丢失,不用自己维护数据重发;三,quic设计有connection id,可以直接识别udp目标,可以用单个udp端口进行数据收发。还是挺期待的

@hedahong
Copy link
Author

对,我说的就是这个意思。多个物理层发包,服务器上聚合。得到的收益除了加速(带宽叠加)外,还有高可用(一套物理线路闪断对应用层透明无感知);另外还有收益就是 极高的加密效果(因为 ,一个应用层的 数据片段,被切分后 由不通的物理网络发出去)

@rhjdvsgsgks
Copy link

rhjdvsgsgks commented Jul 18, 2020

感觉可能有点像我 这条issue ,但我当时只想到了速度方面的收益

另外,如果在 这条issue 的nginx配置的location块中加入

proxy_next_upstream error timeout non_idempotent;
proxy_next_upstream_timeout 1s;

是不是可以算是多出口(多个cdnip)发包,每个包走不同的cdn节点最后在服务器上合并,如果一个节点超时就走下一个节点,因为开启了 non_idempotent 所以会使用下一个节点再试一次发送当前包(参考),但我这样并不能提高速度,最多只能算是提高了可用性,因为只是每个数据包走了不同的“出口”所以并不能提升速度

@genufish
Copy link

个人理解nginx只能做基于数据流的负载均衡。拿下载打比方,nginx只能做到挑选一个好一点的下载链接,但一次只能从一个链接下载。而基于数据包的聚合类似同时从多个下载链接一起下载,每个链接下载其中一部分。

@genufish
Copy link

对,我说的就是这个意思。多个物理层发包,服务器上聚合。得到的收益除了加速(带宽叠加)外,还有高可用(一套物理线路闪断对应用层透明无感知);另外还有收益就是 极高的加密效果(因为 ,一个应用层的 数据片段,被切分后 由不通的物理网络发出去)

刚想到一个问题,不同线路的延迟不同。要是延迟相差大的话,可能快的链路A数据包全到了,慢的链路B数据包还在路上,服务器会认为丢包而要求重发,毕竟接受窗口就那么大,不会干等链路B。

@rhjdvsgsgks
Copy link

rhjdvsgsgks commented Jul 19, 2020

个人理解nginx只能做基于数据流的负载均衡。拿下载打比方,nginx只能做到挑选一个好一点的下载链接,但一次只能从一个链接下载。而基于数据包的聚合类似同时从多个下载链接一起下载,每个链接下载其中一部分。

确实是这样, nginx 实现的只能算是负载均衡,最多只能提升稳定性,并不能提升速度。但我在第一行中提到的 issue 中的想法(与 nginx 无关)个人感觉与您提到的”聚合加速“有一些相似性,都是把一条连接拆成了多条,只不过”聚合加速“是把拆分后的多条连接使用多条物理连接发送,“绕过”了物理连接的速度上限;而我提到的想法更像是“多线程下载”,在同一条物理连接上把一条连接拆分成多条,这些连接可以指向源站也可以是不同的 cdn 节点,绕过的是 cdn /运营商对单条连接速度的限制

@gxlzlu
Copy link

gxlzlu commented Jul 20, 2020

对,我说的就是这个意思。多个物理层发包,服务器上聚合。得到的收益除了加速(带宽叠加)外,还有高可用(一套物理线路闪断对应用层透明无感知);另外还有收益就是 极高的加密效果(因为 ,一个应用层的 数据片段,被切分后 由不通的物理网络发出去)

刚想到一个问题,不同线路的延迟不同。要是延迟相差大的话,可能快的链路A数据包全到了,慢的链路B数据包还在路上,服务器会认为丢包而要求重发,毕竟接受窗口就那么大,不会干等链路B。

可以考虑多用点贷款和流量来解决用户体验问题:慢链路的B数据包还在路上,就在快链路那里再请求数据B,哪个先到就用哪个。目前机场给的流量都足足的,带宽也足足的。就让用户自己权衡是否要用更多的带宽和流量来提升用户体验了。

@gxlzlu
Copy link

gxlzlu commented Jul 20, 2020

负载均衡,肯定会碰到线路快慢的问题,如果快的线路要等慢的线路,就会拉低用户体验。所以要有个比较合适的算法,快的线路要多干活,慢的线路要少干活。可以有冗余的流量,冗余的带宽,但用户体验是至上的。恩,好的用户体验,也是要有成本的,这点大家都能理解的。
现实的情况是,家里的宽带都好几百兆的带宽,机场的流量通常都好几百个G一个月。带宽和流量都有大量冗余,为何不利用上,用于提升用户体验。。

@genufish
Copy link

负载均衡,肯定会碰到线路快慢的问题,如果快的线路要等慢的线路,就会拉低用户体验。所以要有个比较合适的算法,快的线路要多干活,慢的线路要少干活。可以有冗余的流量,冗余的带宽,但用户体验是至上的。恩,好的用户体验,也是要有成本的,这点大家都能理解的。
现实的情况是,家里的宽带都好几百兆的带宽,机场的流量通常都好几百个G一个月。带宽和流量都有大量冗余,为何不利用上,用于提升用户体验。。

很可能慢路99%的数据都会被当丢包。不是快的线路多干活,慢的线路少干活。而是可能快的线路带宽1M延迟1ms,慢的线路带宽100M延迟300ms,结果从慢路走的包全当丢包了。

@gxlzlu
Copy link

gxlzlu commented Jul 20, 2020

你的想法需要服务器端支持。。。基于数据流的负载均衡是选择最优链路/服务器进行数据流传输,传输过程和正常代理没什么差别。基于数据包的聚合加速将数据包在各个链路上同时传送到服务器,然后由服务器重新组合。如果真想做的话,把代理出口传输设成quic,然后把udp包通过不同socks代理发出,在服务器端收到udp包后重组数据流。负载的话可以按最近传输的数据量比例分配,但肯定需要服务器配合重组数据流。用可靠udp协议分流的好处:一,不用考虑各个链路速度差异导致数据到达顺序问题;二,不用考虑单个链路故障导致的部分数据丢失,不用自己维护数据重发;三,quic设计有connection id,可以直接识别udp目标,可以用单个udp端口进行数据收发。还是挺期待的

嗯,基于包来做负载均衡,有点难度。那么,基于请求来做呢?是否轻松一些?

@gxlzlu
Copy link

gxlzlu commented Jul 20, 2020

负载均衡,肯定会碰到线路快慢的问题,如果快的线路要等慢的线路,就会拉低用户体验。所以要有个比较合适的算法,快的线路要多干活,慢的线路要少干活。可以有冗余的流量,冗余的带宽,但用户体验是至上的。恩,好的用户体验,也是要有成本的,这点大家都能理解的。
现实的情况是,家里的宽带都好几百兆的带宽,机场的流量通常都好几百个G一个月。带宽和流量都有大量冗余,为何不利用上,用于提升用户体验。。

很可能慢路99%的数据都会被当丢包。不是快的线路多干活,慢的线路少干活。而是可能快的线路带宽1M延迟1ms,慢的线路带宽100M延迟300ms,结果从慢路走的包全当丢包了。

有这种可能呀!极限情况就是N倍的流量和N倍的带宽。N是负载均衡的链路数。实际上应该不会,1ms的回来了,就把300ms的连接抛弃吧,有无终止该链路指定会话或请求的方法?直到有下一个会话或请求来了,又重新做负载均衡。

@tanyiok1234
Copy link

这么说吧,我个人认为,不管是多个物理接口还是多个不同的传输协议,按数据包做负载均衡:
极限延迟为最快的线路的延迟,此时实际带宽为最快线路带宽;
极限带宽为二者带宽之和,此时实际延迟为最慢线路的延迟;
基本上没有中间值,因为使用慢的线路总会阻塞连接(只要有数据在慢的线路传输,应用层看到的数据传输就被慢的线路阻塞了)
所以大概率没有那种理想中的上策。

作为中策或者下策,主/备份线路切换是可能是一个比较可行的想法,即打满快的线路之后开始使用慢的线路,但是这涉及到一个实时线路测量的问题,需要服务端/客户端双边支持。

在主备份线路切换中,当主线路打满开始丢包/延迟上涨,副线路还没来得及启用时,同样也可能会出现顿卡。所以可能还需要引入fec校验实现少量冗余发包并平滑切换,但同时也牺牲了一定的带宽和延迟。

同时,基于连接的负载均衡应该没啥大用,因为各连接其负载是动态变化的,除非做一个传出连接的迁移的机制来实现动态调度。又或者把传入连接和传出链接解耦。但这都算是粗粒度的调度,不会比上面的情况更好。

总的来说,除非能长时间打满其中一条带宽,否则意义不大,因为目前确实没有好的调度方法。

@genufish
Copy link

这么说吧,我个人认为,不管是多个物理接口还是多个不同的传输协议,按数据包做负载均衡:
极限延迟为最快的线路的延迟,此时实际带宽为最快线路带宽;
极限带宽为二者带宽之和,此时实际延迟为最慢线路的延迟;
基本上没有中间值,因为使用慢的线路总会阻塞连接(只要有数据在慢的线路传输,应用层看到的数据传输就被慢的线路阻塞了)
所以大概率没有那种理想中的上策。

作为中策或者下策,主/备份线路切换是可能是一个比较可行的想法,即打满快的线路之后开始使用慢的线路,但是这涉及到一个实时线路测量的问题,需要服务端/客户端双边支持。

在主备份线路切换中,当主线路打满开始丢包/延迟上涨,副线路还没来得及启用时,同样也可能会出现顿卡。所以可能还需要引入fec校验实现少量冗余发包并平滑切换,但同时也牺牲了一定的带宽和延迟。

同时,基于连接的负载均衡应该没啥大用,因为各连接其负载是动态变化的,除非做一个传出连接的迁移的机制来实现动态调度。又或者把传入连接和传出链接解耦。但这都算是粗粒度的调度,不会比上面的情况更好。

总的来说,除非能长时间打满其中一条带宽,否则意义不大,因为目前确实没有好的调度方法。

极限延迟的话所有链路发同样数据先到为准,极限带宽的话要一个够大的接收窗口进行组合数据流。
还是考虑设定一个可接受延迟,大于这个延迟的链接直接抛弃也许会好一些。或者以所有链路中延迟最小的为基准,超过10ms以上的全部抛弃。假设接收窗口16K大小,链路网速都是1M/s,延迟相差超过16ms的话,窗口就在干等慢链路了。
延迟相差太大的链路感觉没有捆绑价值,慢的链路b不断被认为丢包,快的链路a不断重传,最后结果就是链路a传了所有数据,链路b做白工还占流量。

@tanyiok1234
Copy link

这么说吧,我个人认为,不管是多个物理接口还是多个不同的传输协议,按数据包做负载均衡:
极限延迟为最快的线路的延迟,此时实际带宽为最快线路带宽;
极限带宽为二者带宽之和,此时实际延迟为最慢线路的延迟;
基本上没有中间值,因为使用慢的线路总会阻塞连接(只要有数据在慢的线路传输,应用层看到的数据传输就被慢的线路阻塞了)
所以大概率没有那种理想中的上策。
作为中策或者下策,主/备份线路切换是可能是一个比较可行的想法,即打满快的线路之后开始使用慢的线路,但是这涉及到一个实时线路测量的问题,需要服务端/客户端双边支持。
在主备份线路切换中,当主线路打满开始丢包/延迟上涨,副线路还没来得及启用时,同样也可能会出现顿卡。所以可能还需要引入fec校验实现少量冗余发包并平滑切换,但同时也牺牲了一定的带宽和延迟。
同时,基于连接的负载均衡应该没啥大用,因为各连接其负载是动态变化的,除非做一个传出连接的迁移的机制来实现动态调度。又或者把传入连接和传出链接解耦。但这都算是粗粒度的调度,不会比上面的情况更好。
总的来说,除非能长时间打满其中一条带宽,否则意义不大,因为目前确实没有好的调度方法。

极限延迟的话所有链路发同样数据先到为准,极限带宽的话要一个够大的接收窗口进行组合数据流。
还是考虑设定一个可接受延迟,大于这个延迟的链接直接抛弃也许会好一些。或者以所有链路中延迟最小的为基准,超过10ms以上的全部抛弃。假设接收窗口16K大小,链路网速都是1M/s,延迟相差超过16ms的话,窗口就在干等慢链路了。
延迟相差太大的链路感觉没有捆绑价值,慢的链路b不断被认为丢包,快的链路a不断重传,最后结果就是链路a传了所有数据,链路b做白工还占流量。

所以说只要A带宽没被打满,发包狠一点全部扔给A就好了,因为B被认为丢包然后A重传至少是2个A的RTT了(当然B在做无用功,如果B要真的在传输数据的话就是1个B的RTT加上一个A的RTT了)。
况且说实话跨国线路延迟不仅差异大,而且还飘的很。

@genufish
Copy link

genufish commented Aug 11, 2020

https://github.com/multipath-tcp/mptcp
找到一个内核级多TCP聚合。。。不过要给linux内核打补丁。。。

维基百科对多链路TCP的说明 https://en.wikipedia.org/wiki/Multipath_TCP
RFC6824基本停滞在实验层面 https://tools.ietf.org/html/rfc6824

SCTP和多路径QUIC也许可以看看

@fbion
Copy link

fbion commented Aug 13, 2020

mark

@github-actions
Copy link

This issue is stale because it has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants