[GH-ISSUE #3243] all quic traffic from frpc to frps stalls #2603

Closed
opened 2026-05-05 13:40:44 -06:00 by gitea-mirror · 1 comment
Owner

Originally created by @delaneyb on GitHub (Jan 7, 2023).
Original GitHub issue: https://github.com/fatedier/frp/issues/3243

Bug Description

The new quic support is great! For static file downloads I was able to increase throughput from 4MB/s to around 13MB/s simply by switching to the new protocol = quic. Unfortunately my excitement was short lived as the tunnel would stop working entirely when I started trying to seek around a video served through the frp tunnel from my Jellyfin media server. Restarting the tunnel would always fix the problem until you seek on the video again a few times. A minimal repro can be made by simply opening a tunnel to a local http server which is serves a video file and dragging the playhead in the browser to generate a bunch of requests:

https://user-images.githubusercontent.com/18545667/211148931-63a3056d-a2d7-43bb-b86c-1446f396971f.mp4

It seems to vary how many times you can seek around the video, some times only once would cause the tunnel to break, others maybe 10 or more times. I have found dragging the playhead around the video will guarantee to trigger the issue.

I have spent a couple days now wrapping my head around the codebase and learning go to try and understand where the issue was occurring. Today I found a hacky solution that solves the video seeking issue at least temporarily.

index fc59b39..6570323 100644
--- a/server/service.go
+++ b/server/service.go
@@ -218,6 +218,13 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
                        MaxIdleTimeout:     time.Duration(cfg.QUICMaxIdleTimeout) * time.Second,
                        MaxIncomingStreams: int64(cfg.QUICMaxIncomingStreams),
                        KeepAlivePeriod:    time.Duration(cfg.QUICKeepalivePeriod) * time.Second,
+                       // I believe the key thing is the initial connection receive window
+                       MaxConnectionReceiveWindow:     1e+8,      // 100MB
+                       InitialConnectionReceiveWindow: 1e+8,
+                       MaxStreamReceiveWindow:         1e+8 / 50, // Was just testing different settings here, don't think there is anything specific about the /50 that makes this work vs just using e.g. 15MB but I assume this needs to be LESS than MaxConnectionReceiveWindow as I believe the core problem is that the connection receive window allowance is exhausted by unclosed streams or something thus preventing any more data from being sent
+                       InitialStreamReceiveWindow:     128,       // On an individual stream start the receive window tiny
                })
                if err != nil {
                        err = fmt.Errorf("listen on quic udp address %s error: %v", address, err)

With this change in place the quic connection no longer breaks down BUT both frpc and frps memory usage continues increasing as I drag the playhead around the video (after doing so for about 30s I observed ~50MB memory usage on windows), I would assume indicating that there are a bunch of quic streams that are not being closed or something.

frpc Version

1.46.0

frps Version

1.46.0

System Architecture

Observed on linux/amd64, windows/x86_64, linux_arm64, darwin

Configurations

frpc.ini

[common]
server_addr = localhost
server_port = 7000
protocol = quic
log_level = debug

[tcp-service]
type = tcp
local_ip = localhost
local_port = 3000
remote_port = 8080

frps.ini

[common]
bind_port = 7000
quic_bind_port = 7000
log_level = debug

Logs

frpc.log
frps.log

Steps to reproduce

  • Run a frps with a quic port and have frpc connect opening a tunnel for tcp traffic to an application serving a video file
  • Access and attempt to seek a few times within the video file served over the tunnel
  • Observe eventually frpc traffic is no longer being transmitted back to frps. Frps receives the requests from the browser, and frpc even gets the ReqWorkConn messages, but no StreamFrames are transmitted back from frpc to frps anymore

Affected area

  • Docs
  • Installation
  • Performance and Scalability
  • Security
  • User Experience
  • Test and Release
  • Developer Infrastructure
  • Client Plugin
  • Server Plugin
  • Extensions
  • Others
Originally created by @delaneyb on GitHub (Jan 7, 2023). Original GitHub issue: https://github.com/fatedier/frp/issues/3243 ### Bug Description The new quic support is great! For static file downloads I was able to increase throughput from 4MB/s to around 13MB/s simply by switching to the new `protocol = quic`. Unfortunately my excitement was short lived as the tunnel would stop working entirely when I started trying to seek around a video served through the frp tunnel from my Jellyfin media server. Restarting the tunnel would always fix the problem until you seek on the video again a few times. A minimal repro can be made by simply opening a tunnel to a local http server which is serves a video file and dragging the playhead in the browser to generate a bunch of requests: https://user-images.githubusercontent.com/18545667/211148931-63a3056d-a2d7-43bb-b86c-1446f396971f.mp4 It seems to vary how many times you can seek around the video, some times only once would cause the tunnel to break, others maybe 10 or more times. I have found dragging the playhead around the video will guarantee to trigger the issue. I have spent a couple days now wrapping my head around the codebase and learning go to try and understand where the issue was occurring. Today I found a hacky solution that solves the video seeking issue at least temporarily. ```diff index fc59b39..6570323 100644 --- a/server/service.go +++ b/server/service.go @@ -218,6 +218,13 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) { MaxIdleTimeout: time.Duration(cfg.QUICMaxIdleTimeout) * time.Second, MaxIncomingStreams: int64(cfg.QUICMaxIncomingStreams), KeepAlivePeriod: time.Duration(cfg.QUICKeepalivePeriod) * time.Second, + // I believe the key thing is the initial connection receive window + MaxConnectionReceiveWindow: 1e+8, // 100MB + InitialConnectionReceiveWindow: 1e+8, + MaxStreamReceiveWindow: 1e+8 / 50, // Was just testing different settings here, don't think there is anything specific about the /50 that makes this work vs just using e.g. 15MB but I assume this needs to be LESS than MaxConnectionReceiveWindow as I believe the core problem is that the connection receive window allowance is exhausted by unclosed streams or something thus preventing any more data from being sent + InitialStreamReceiveWindow: 128, // On an individual stream start the receive window tiny }) if err != nil { err = fmt.Errorf("listen on quic udp address %s error: %v", address, err) ``` With this change in place the quic connection no longer breaks down **BUT** both frpc and frps memory usage continues increasing as I drag the playhead around the video (after doing so for about 30s I observed ~50MB memory usage on windows), I would assume indicating that there are a bunch of quic streams that are not being closed or something. ### frpc Version 1.46.0 ### frps Version 1.46.0 ### System Architecture Observed on linux/amd64, windows/x86_64, linux_arm64, darwin ### Configurations frpc.ini ``` [common] server_addr = localhost server_port = 7000 protocol = quic log_level = debug [tcp-service] type = tcp local_ip = localhost local_port = 3000 remote_port = 8080 ``` frps.ini ``` [common] bind_port = 7000 quic_bind_port = 7000 log_level = debug ``` ### Logs [frpc.log](https://github.com/fatedier/frp/files/10366135/frpc.log) [frps.log](https://github.com/fatedier/frp/files/10366136/frps.log) ### Steps to reproduce - Run a frps with a quic port and have frpc connect opening a tunnel for tcp traffic to an application serving a video file - Access and attempt to seek a few times within the video file served over the tunnel - Observe eventually frpc traffic is no longer being transmitted back to frps. Frps receives the requests from the browser, and frpc even gets the ReqWorkConn messages, but no StreamFrames are transmitted back from frpc to frps anymore ### Affected area - [ ] Docs - [ ] Installation - [X] Performance and Scalability - [ ] Security - [X] User Experience - [ ] Test and Release - [ ] Developer Infrastructure - [X] Client Plugin - [ ] Server Plugin - [ ] Extensions - [ ] Others
gitea-mirror 2026-05-05 13:40:44 -06:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@fatedier commented on GitHub (Jan 9, 2023):

@delaneyb Thanks for your feedback and your detail infos. It helps me a lot.

I find that the bug maybe caused by Close() of quic stream. Releated issue https://github.com/lucas-clemente/quic-go/issues/3558

We need to call CancelRead() too. I will fix it soon.

<!-- gh-comment-id:1375377053 --> @fatedier commented on GitHub (Jan 9, 2023): @delaneyb Thanks for your feedback and your detail infos. It helps me a lot. I find that the bug maybe caused by `Close()` of quic stream. Releated issue https://github.com/lucas-clemente/quic-go/issues/3558 We need to call `CancelRead()` too. I will fix it soon.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#2603
No description provided.