One of the nginx maintainers responded
<https://trac.nginx.org/nginx/ticket/959> to my bug report and explained
how it uses flow control windows:
“The request body cannot be read and processed by nginx until some module
asks for it. To prevent the client from sending the request body that
hasn’t been asked yet, the stream’s window is kept zero.”
As I understand this, nginx sets the default window size to 0 for all
streams. The flow control window isn’t expanded from 0 until nginx finds a
module to accept the request. In terms of round trips this seems like a
regression from HTTP/1.1:
HTTP/1.1 connection
→ client sends request headers + body
← server responds with response headers + body
HTTP/2 connection with a default stream window size of 0
→ client sends request headers
← server expands flow control window
→ client sends request body
← server responds with response headers and response body
This is a surprising and disappointing regression for the common case, in
which the server accepts the request body. It’s particularly problematic
for HTTP APIs because they usually include request bodies.
I’ll continue to petition the nginx maintainers to optimistically buffer a
small incoming request body. Buffering at most 64 KiB per request would
save a network roundtrip! I think that’s an inexpensive and non-complicated
way for them to improve performance.
– Jesse