HTTP/2 body pipe sends 1-byte DATA frames when a stream holds a sliver of capacity
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 74/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- rust
- Lĩnh vực
- networking, performance
Hướng nghiên cứu
Start in src/proto/h2/mod.rs at PipeToSendStream, then run the regression test h2_chunk_waits_for_useful_capacity_instead_of_sliver_frames from the linked PR. Trace how capacity is claimed before send_data; done means Stream B no longer emits a 1-byte initial DATA frame when only a sliver of connection capacity is available.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Version
hyper 1.9.0 through master (c954d80), with h2 0.4.19.
Platform
Any. Seen on Linux and macOS.
Description
When a stream holds only a tiny amount of send capacity, the HTTP/2 client and server body pipe (PipeToSendStream in src/proto/h2/mod.rs) hands a body chunk to h2 anyway, and h2 splits it into DATA frames sized to that capacity. The body then goes out as a 1-byte DATA frame, followed by more small frames as capacity trickles in (silly-window syndrome).
On master, the pipe reserves a 1-byte claim once a chunk is in hand, then calls send_data as soon as capacity() > 0. hyper 1.9.0 reserved the byte before polling the body; the result is the same. On a connection whose window is nearly used up, that one byte is often all the stream has been assigned, so the first frame carries a single byte of a 10 KB chunk.
This used to cost only framing overhead. Since h2 0.4.16, it breaks connections. h2 servers (tonic, axum, hyper) now charge every non-final DATA frame under 256 bytes against a per-connection budget (DEFAULT_DATA_FRAME_OVERHEAD_THRESHOLD, a minimum of 25600). When that budget runs out they send GOAWAY(ENHANCE_YOUR_CALM, "too_many_data_frames"), and every in-flight stream on the connection fails.
We hit this in a reverse proxy that keeps pooled HTTP/2 connections to a hyper backend with adaptive_window(true). Adaptive windows start at 65535, so a busy pooled connection often uses up its connection window. A frame trace showed about 2,900 frames of sz=10240, available=1 in 4 seconds, and the backend GOAWAY'd the pooled connection every few seconds.
Reproduction
The regression test in the linked PR (h2_chunk_waits_for_useful_capacity_instead_of_sliver_frames) reproduces it deterministically:
- Stream A sends 65534 bytes, which the server does not release, leaving one byte of connection window.
- Stream B then sends a 10 KB body.
- On
master, stream B's first DATA frame is 1 byte.
Proposed fix
Keep the small claim that #4003 depends on, but make it big enough to cut a useful frame. Reserve min(len, 1024) and wait until that much is assigned before calling send_data. 1 KiB is well below any stream window a real peer advertises, so this cannot hold a chunk back indefinitely, and it rules out sub-256-byte frames.
- Ngôn ngữ chính
- Rust
- Star
- 16.4k
- Fork
- 1.8k
- Merge trung bình
- 2 ngày 9 giờ
- Pull request đã merge (30 ngày)
- 14
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của hyperium/hyper
-
Publicly reexport the http crateĐang mởC-feature
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 65/100
hyperium/hyper#2652 · 4 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug(ci): some warnings are not enforced by `features` stepCó thể đã có người làm @cratelyn đã nhận 3 ngày trước. Đang mởA-tests C-bug
hyperium/hyper#4232 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Write a HIP for `Body::poll_progress()`Có thể đã có người làm @cratelyn đã nhận 9 ngày trước. Đang mởA-body B-rfc C-feature
hyperium/hyper#4228 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Upgraded HTTP/2 CONNECT streams cannot be reset, so a failed tunnel looks like a clean closeCó thể đã có người làm @jeremyjpj0916 đã nhận 19 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 55/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Allow connection pools to stop reusing an HTTP/2 connection before its keep-alive timeoutCó thể đã có người làm @jiahaoliang đã nhận 37 ngày trước. Đang mởC-feature
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
hyperium/hyper#4186 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của hyperium/hyper
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
pop-os/cosmic-comp#2956 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
libp2p/rust-libp2p#6694 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Stack overflow in `check bans` with `include-dependencies = true` and a dev-dependency cycleĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
EmbarkStudios/cargo-deny#910 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
tursodatabase/turso#10054 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
build: Update rust versionCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởdependencies
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
ibm-granite-community/granite-cli#229 ·
Maintainer thường phản hồi trong vòng 1 ngày