diff --git a/doc/configuration.txt b/doc/configuration.txt index 52c5bdfdf..8d2e7605f 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -5321,17 +5321,26 @@ tune.quic.frontend.stream-data-ratio <0..100, in percent> (deprecated) tune.quic.be.stream.max-concurrent tune.quic.fe.stream.max-concurrent - Sets the QUIC initial_max_streams_bidi transport parameter either on frontend - or backend side. This is the maximum number of bidirectional streams that the - remote peer will be authorized to open concurrently during the connection - lifetime. On frontend side, this limits the number of concurrent HTTP/3 - client requests. + On frontend side, this is used as the value for the advertised + initial_max_streams_bidi transport parameter. This is enforced as the maximum + number of bidirectional streams that the remote peer will be authorized to + open concurrently during the connection lifetime. This effectively limits the + number of concurrent HTTP/3 client requests. The default value is 100. Note that if you reduces it, it can restrict the buffering capabilities of streams on receive, which would result in poor upload throughput. It can be corrected by increasing the QUIC stream rxbuf connection setting. + On backend side, this is enforced locally by haproxy to limit the number of + concurrent requests multiplexed over a single connection. This may be further + restricted by the peer flow control. It may be necessary to reduce the + default value of 100 to improve a site's responsiveness at the expense of a + higher number of opened backend connections. Similarly to the frontend side, + this setting also directly impacts the Rx buffering capability, this time + though limiting the HTTP download capacity. QUIC stream rxbuf setting can be + increased when dealing mostly with HTTP responses larger than "tune.bufsize". + See also: "tune.quic.be.stream.rxbuf", "tune.quic.fe.stream.rxbuf", "tune.quic.be.stream.data-ratio", "tune.quic.fe.stream.data-ratio" diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index 5293c204b..ae4a58846 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,9 @@ static inline void qcs_wait_http_req(struct qcs *qcs) BUG_ON_HOT(qcs->flags & QC_SF_HREQ_RECV); qcs->flags |= QC_SF_HREQ_RECV; ++qcc->nb_hreq; + + /* On BE side avail_streams cb should prevent opening of too many concurrent streams. */ + BUG_ON(conn_is_back(qcc->conn) && qcc->nb_hreq > quic_tune.be.stream_max_concurrent); } void qcc_show_quic(struct qcc *qcc); diff --git a/src/mux_quic.c b/src/mux_quic.c index b5f1375b4..b36799a6b 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -3341,6 +3341,10 @@ static int qcm_avail_streams(struct connection *conn) ret = qcc_fctl_avail_streams(qcc, 1); + /* Enforce stream_max_concurrent limit even if peer allows more streams. */ + if (ret > quic_tune.be.stream_max_concurrent - qcc->nb_hreq) + ret = quic_tune.be.stream_max_concurrent - qcc->nb_hreq; + /* Now cap return value if reaching max-reuse server or maximum stream * ID. qcc_be_is_reusable() already detected if one of these has been * exceeded. @@ -4199,6 +4203,10 @@ static void qcm_strm_detach(struct sedesc *sd) qcs->flags |= QC_SF_DETACH; qcc_refresh_timeout(qcc); + /* TODO on backend side if a QCS is detached, the connection may + * not be reinserted in the correct server pool (idle or avail). + */ + TRACE_LEAVE(QMUX_EV_STRM_END, qcc->conn, qcs); return; } diff --git a/src/quic_tp.c b/src/quic_tp.c index e85f8b58d..75243b44d 100644 --- a/src/quic_tp.c +++ b/src/quic_tp.c @@ -71,7 +71,7 @@ void quic_transport_params_init(struct quic_transport_params *p, int server) quic_tune.be.max_idle_timeout; /* Set limit on number of concurrently opened streams. */ - p->initial_max_streams_bidi = max_streams_bidi; + p->initial_max_streams_bidi = server ? max_streams_bidi : 0; p->initial_max_streams_uni = max_streams_uni; /* Set connection flow-control data limit, either from configuration,