mirror of
https://github.com/fatedier/frp.git
synced 2026-05-15 08:05:49 -06:00
[GH-ISSUE #2987] tcpmux 会大幅降低链路速度 #2384
Labels
No labels
In Progress
WIP
WaitingForInfo
bug
doc
duplicate
easy
enhancement
future
help wanted
invalid
lifecycle/stale
need-issue-template
need-usage-help
no plan
proposal
pull-request
question
todo
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/frp#2384
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @shiyunjin on GitHub (Jun 17, 2022).
Original GitHub issue: https://github.com/fatedier/frp/issues/2987
Bug Description
仅创建一个tcp内网穿透连接
修改选项
tcp_mux = true开启tcp_mux 测速得 10-15 Mbps
关闭tcp_mux 测速得 100 Mbps
frpc Version
0.42.0
frps Version
0.42.0
System Architecture
linux/amd64
Configurations
[common]
server_addr = *****
server_port = 3000
token = *****
heartbeat_interval = 3
heartbeat_timeout = 10
tcp_mux = true
pool_count = 1
Logs
No response
Steps to reproduce
No response
Affected area
@shiyunjin commented on GitHub (Jun 17, 2022):
测速方向 frpc客户端(源)->frps服务端(下载)
@shiyunjin commented on GitHub (Jun 17, 2022):
https://github.com/hashicorp/yamux/issues/24
@shiyunjin commented on GitHub (Jun 17, 2022):
kcptun 2016年的时候使用yamux也出现了同样的问题
https://github.com/xtaci/kcptun/issues/126
@shiyunjin commented on GitHub (Jun 17, 2022):
我已经自行将frp中的
yamux替换为 https://github.com/xtaci/smux速度已经达到正常水平

在我这里问题解决了,如有觉得必要官方可以也进行替换. (本issues可以随时关闭)
@fatedier commented on GitHub (Jun 19, 2022):
目前不会替换,稳定性比速度更重要,v2 中可能会倾向于使用 QUIC。
@github-actions[bot] commented on GitHub (Jul 20, 2022):
Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.
@hayden-pan commented on GitHub (Aug 24, 2022):
经过分析,发现了yamux和smux在速度上存在的区别的可能原因。smux的第一个版本协议里,只有一整个session的接收缓冲区,所有的stream共用,这导致了smux可以减少很多在yamux上使用的缓冲区通信,因为每次的缓冲区通信需要一个TTL时间,所以降低了速度,但是重点来了,这个设计会有一个严重的问题,当某个stream有问题,占用满了整个session缓冲区时,会影响同一个session下的所有stream,所以后来smux开发了v2版本添加了和yamux一样的stream缓冲区控制逻辑,但是如果用户没有特别指定使用v2版本,默认是使用v1版本。所以想问下当时您测试的环境使用的是V2还是V1版本?
那么接下来说说我自己在排除这个TTL影响的情况下测试(因为做包含TTL的测试比较麻烦,让我偷懒一下 : ) )
我本地直接复制了yamux的bechmark测试代码(smux没有benchmark代码),因为yamux和smux的对外接口很像,所以基本没有问题,yamux的测试代码是直接在本地内存拷贝模拟的网络IO,所以基本没有延迟,这个测试主要是测试代码的CPU和内存消耗以及操作速度,直接说结论,都是yamux胜出。全部都使用默认配置。
欢迎大家一起讨论
yamux
smux(v1)
smux(v2)
@shiyunjin commented on GitHub (Aug 24, 2022):
使用的是smux v1
所谓的smux v2最后更新时间为2019年,而v1是2021年。
我刚才简单测试了一下smux v2也存在吞吐量低的问题
这个问题不必过于纠结,我自己现在自用的版本已经满足我的需求了。可能对于绝大多数人来说稳定比速度更为重要
@hayden-pan commented on GitHub (Aug 24, 2022):
我也只是最近在研究这两个库,看到了相关的讨论顺便回复一下
@hayden-pan commented on GitHub (Aug 26, 2022):
使用QUIC的日子可能不会那么快到来,我有个建议,是不是可以给在启用tcpmux的时候,可以设置yamux的stream最大缓冲大小。yamux默认的最大缓冲大小为256KB,这个缓冲比较保守。
这样当每个stream实际可用速度大于 256KB/RTT 的时候就至少受一个TTL时间的缓冲等待影响。
假设当前client和server的RTT为50ms,当速度要大于 256KB*(1000ms/50ms) = 5MB/s = 40Mb/s 时,就要等待一个RTT时间来确认缓冲区,这个传输时间的影响最大是多等待一个RTT,速度会降到 20Mb/s左右。那么在这种RTT稳定为50ms的情况下,即使CPU运算再快,带宽再大,速度也不可能提升,而相应的提高这个最大缓存带入公式可以得到相应的速度提升(这个速度是指每个stream的最大速度)。
这个缓冲区设置可以针对实际的网络使用情况进行优化。例如,如果网络传输为常规的网页访问,小的请求头,比较大的下行,那么只需要提高Client这一端的缓存,反之也是如此。当这个缓存提高到10MB这个RTT影响会比较小了,甚至当网络传输不大于5MB的时候不会受到这个RTT的影响。
再来说这个缓冲调大后带来的问题,假如Client端的缓存调整为10MB,只要Client端读取没有出现阻塞,一个stream所占用的内存也并不会大到10MB。所以我觉得对处于安全网络环境的frp用户可以根据自己的需要调整这个大小,优化自己的网络。给用户一个选择的机会,也是一个用空间换时间的做法
@fatedier commented on GitHub (Aug 26, 2022):
@aaftio 可以考虑,是否可以有相应的测试数据来说明其影响?
@hayden-pan commented on GitHub (Aug 26, 2022):
可以,但是大带宽环境我只有局域网环境,并且由于延迟只有5ms左右,应该只有很大的数据包传输才能看到效果,等我试试
@fatedier commented on GitHub (Aug 26, 2022):
linux 下可以使用
tc模拟丢包和延迟,可以直接在单机环境测试。@romotc commented on GitHub (Oct 16, 2022):
方便把替换成smux之后的代码开源一下吗?
@Triangleowl commented on GitHub (May 8, 2023):
通过调大yamux.Config.MaxStreamWindowSize(默认大小为256*1024,不能低于此值)可以缓解限速问题。如果带宽比较大的情况下,使用yamux做多路复用,假设多路复用客户端和服务端的RTT
tms,则单个stream的带宽约为:((1000/t) * (MaxStreamWindowSize/2) * 8)/(1024*1024)Mbps@hayden-pan commented on GitHub (May 8, 2023):
近段工作生活变化很大,没有花时间在这上面了,所以鸽了,只能等有时间了再折腾这块
@hayden-pan commented on GitHub (May 8, 2023):
如之前的交流,是想以测试结果来验证理论,如果方便有时间你可以帮忙发个测试结果么。
@Triangleowl commented on GitHub (May 8, 2023):
这个是我使用yamux做代理测试的结果(自己写的一个简单的多路复用代理,没有用frp)。从实验结果来看,通过调大yamux.Config.MaxStreamWindowSize可以缓解带宽限制,这个限制只针对_单个stream_。比如带宽的物理限制是100Mbps,使用了多路复用后单个stream被限制到10Mbps,则开启两个stream时,两个stream都能达到10Mbps。
@hayden-pan commented on GitHub (May 8, 2023):
谢谢你的数据。 我刚刚才看到现在已经支持 QUIC 了!这个似乎已经不那么急了 。
@fatedier 这个测试虽然没有通过改变 RTT 来验证是 RTT 对传输速度上限的影响,但是验证了在相同的 RTT 下,不同的最大缓冲区对传输上限的影响。当然在提供这个参数设置的时候,为了更好去解释这个参数,还需要提供 Client 端的设置值和 Server 端的设置值对不同传输场景的影响。如果还是觉得添加这个配置的条件不足,再等等我有时间提供再详细的测试数据。
@fatedier commented on GitHub (May 8, 2023):
@Triangleowl @aaftio 非常感谢你们提供的数据和对这方面的研究。
我自己对于 yamux 的各个参数细节可能没有精力深入,所以相对会比较谨慎。如果确实能解决问题,提供参数配置也没问题。
@shiyunjin commented on GitHub (Jan 30, 2025):
I believe what you're looking for is imux, a reverse multiplexing library.
For example: https://github.com/hkparker/imux
I have a private fork of imux that uses multiple gRPC connections to support a single data path.
Of course, this solution primarily addresses bandwidth throttling on a single connection.
A better system-level solution you might need could be Multipath TCP.