HTTP/2 body pipe sends 1-byte DATA frames when a stream holds a sliver of capacity
Los mantenedores suelen responder en 2 días
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 74/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- rust
- Área
- networking, performance
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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.
- Lenguaje dominante
- Rust
- Estrellas
- 16.4k
- Forks
- 1.8k
- Merge medio
- 5 d 17 min
- PR fusionados (30 d)
- 19
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de hyperium/hyper
-
Publicly reexport the http crateAbiertoC-feature
Dificultad 1/5 Menos de una hora Aptitud para principiantes 65/100
hyperium/hyper#2652 · 4 reacciones ·
Los mantenedores suelen responder en 2 días
-
Write a HIP for `Body::poll_progress()`Posiblemente ocupada @cratelyn la tomó hace 5 días. AbiertoA-body B-rfc C-feature
hyperium/hyper#4228 · 1 asignado ·
Los mantenedores suelen responder en 2 días
-
Upgraded HTTP/2 CONNECT streams cannot be reset, so a failed tunnel looks like a clean closePosiblemente ocupada @jeremyjpj0916 la tomó hace 14 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
Los mantenedores suelen responder en 2 días
-
Allow connection pools to stop reusing an HTTP/2 connection before its keep-alive timeoutPosiblemente ocupada @jiahaoliang la tomó hace 32 días. AbiertoC-feature
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
hyperium/hyper#4186 · 2 comentarios ·
Los mantenedores suelen responder en 2 días
-
HTTP/1 client connection is never closed or pooled when a response completes while the request body is still unsent ((Reading::KeepAlive, Writing::Body) is a terminal state)Quizá libre de nuevo @BlackRabbitCoder la tomó hace 28 días y no hay ningún pull request abierto. AbiertoC-bug
hyperium/hyper#4176 · 6 comentarios · 1 asignado ·
Los mantenedores suelen responder en 2 días
Todos los issues de hyperium/hyper
Issues similares
-
Docs: refresh target-app-parity and file-format-parity against mainPosiblemente ocupada @vangel76 la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
storytold/photocraft#4417 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
bevyengine/dlss_wgpu#37 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
-
wgpu error: Validation ErrorAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 63/100
bherbruck/solvecraft#369 ·
-
enhancement
Dificultad 1/5 Menos de una hora Aptitud para principiantes 83/100
alunduil/git-worktree-poi#11 ·