tuic icon indicating copy to clipboard operation
tuic copied to clipboard

Bug: `quinn::connection::Connection::open_bi` will hang when reach `max_concurrent_bi_streams` limit

Open finpluto opened this issue 2 years ago • 2 comments

Bug: 当同时开启的stream数到达quinn的max_concurrent_bi_streams(默认为100)上限后,调用quinn::connection::Connection::open_bi()将会挂起task,导致连接超时。

可以考虑的解决方案:

  1. tuic_client::relay::connection::Connection::get_bi_stream()处通过Register的流计数实现自动扩容流上限
  2. 加入可配置项允许用户设置max_concurrent_bi_streams
  3. 创建quic::connection::Connection时调用set_max_concurrent_bi_streams设置为更大值

Bug: quinn::connection::Connection::open_bi will hang when reach max_concurrent_bi_streams limit, cause relay task timeout.

possible solutions:

  1. make tuic_client::relay::connection::Connection::get_bi_stream() call expand max_concurrent_bi_streams automatically;
  2. add a configuration option to allow customizing the value of max_concurrent_bi_stream;
  3. call set_max_concurrent_bi_streams with a number larger than 100 when creating quic::connection::Connection

refs:

  • https://github.com/quinn-rs/quinn/issues/1231#issuecomment-1008331336

finpluto avatar Sep 15 '22 08:09 finpluto

image_2022-09-14_22-23-13

connection完成超时(大于1分钟)的统计图表。 a connection finish time tracing diagram.

finpluto avatar Sep 15 '22 08:09 finpluto

临时补丁/workaround patch

client:

diff --git a/client/src/relay/connection.rs b/client/src/relay/connection.rs
index 1face7d..d4accc7 100644
--- a/client/src/relay/connection.rs
+++ b/client/src/relay/connection.rs
@@ -163,6 +163,9 @@ impl Connection {
             conn.await?
         };
 
+        connection.set_max_concurrent_bi_streams(65536u32.into());
+        connection.set_max_concurrent_uni_streams(65536u32.into());
+
         let conn = Self::new(connection, config).await;
         let uni_streams = IncomingUniStreams::new(uni_streams, conn.stream_reg.get_registry());
 

server:

diff --git a/server/src/connection/mod.rs b/server/src/connection/mod.rs
index a4c8ff0..b2904a2 100644
--- a/server/src/connection/mod.rs
+++ b/server/src/connection/mod.rs
@@ -59,6 +59,9 @@ impl Connection {
                 let is_closed = IsClosed::new();
                 let is_authed = IsAuthenticated::new(is_closed.clone());
 
+                connection.set_max_concurrent_uni_streams(65536u32.into());
+                connection.set_max_concurrent_bi_streams(65536u32.into());
+
                 let conn = Self {
                     controller: connection,
                     udp_packet_from: UdpPacketFrom::new(),

修改后会有比较大的内存占用。

may cause dramatic memory consumption.

finpluto avatar Sep 15 '22 08:09 finpluto

最近正在重构,打算用思路 1 解决这个问题。

quinn 的文档中提到的 max_concurrent_uni_streams

Modify the number of remotely initiated unidirectional streams that may be concurrently open

因此 max_concurrent_uni_streams 的数值应只会影响 streams initiated by peer。目前 TUIC 的 register 只针对 task 进行计数,没有区分 stream 流向,所以需要重构这一部分

EAimTY avatar Oct 07 '22 05:10 EAimTY