You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
HTTP/2 POST loop fails with ENHANCE_YOUR_CALM after 40701 iterations #23116
if((session->opt_flags&NGHTTP2_OPTMASK_NO_CLOSED_STREAMS)==0&&session->server&&!is_my_stream_id&&nghttp2_stream_in_dep_tree(stream)){/* On server side, retain stream at most MAX_CONCURRENT_STREAMS combined with the current active incoming streams to make dependency tree work better. */nghttp2_session_keep_closed_stream(session,stream);}else{rv=nghttp2_session_destroy_stream(session,stream);if(rv!=0){returnrv;}}
I think this is going to cause a failure for any Node.js HTTP/2 app which processes many requests in the same session, due to tracking and limiting current_nghttp2_memory_ in node_http2.cc.
Note in the conditional above, !is_my_stream_id is checking that the stream is an incoming request and nghttp2_stream_in_dep_tree(stream) is checking the stream is in the dependency tree.
I'm seeing both true in the logs. The requests are inserted as dependencies of the root, e.g.:
To clarify, a single session would keep around 232 bytes for every stream that was closed?
Use of the no_closed_streams option is not ideal because it prevents nghttp2 from performing a number of security and state checks.
From the nghttp2 docs, it seems nghttp2_option_set_no_closed_streams is only doing
This option prevents the library from retaining closed streams to maintain the priority tree. If this option is set to nonzero, applications can discard closed stream completely to save memory.
Ah, right, given that we're not really make use of priority, this likely can be switched off. Still, in this particular use case, I would still set a significantly higher maxSessionMemory.
If I increase maxSessionMemory to 100Mb, the server starts failing requests after 400k of them on a session.
The Web page has no way of resetting its session with the server - the fetch API has no way to tell the browser to use a new connection when the failures start (unless I've missed something).
So this means long running sessions to Node over HTTP/2 don't work reliably.
Activity
davedoesdev commentedon Sep 27, 2018
The relevant code in nghttp2 is here: https://github.com/nodejs/node/blob/v10.10.0/deps/nghttp2/lib/nghttp2_session.c#L1211
I think this is going to cause a failure for any Node.js HTTP/2 app which processes many requests in the same session, due to tracking and limiting
current_nghttp2_memory_innode_http2.cc.lpinca commentedon Sep 27, 2018
cc: @nodejs/http2
davedoesdev commentedon Sep 27, 2018
Note in the conditional above,
!is_my_stream_idis checking that the stream is an incoming request andnghttp2_stream_in_dep_tree(stream)is checking the stream is in the dependency tree.I'm seeing both true in the logs. The requests are inserted as dependencies of the root, e.g.:
jasnell commentedon Sep 27, 2018
This is specifically there to prevent denial of service attacks. It is possible to change the default maximum session memory limit using the
maxSessionMemoryoption (https://nodejs.org/dist/latest-v10.x/docs/api/http2.html#http2_http2_createserver_options_onrequesthandler). Use of theno_closed_streamsoption is not ideal because it prevents nghttp2 from performing a number of security and state checks.Try setting a significantly higher
maxSessionMemorylimit and giving it another go.mcollina commentedon Sep 27, 2018
To clarify, a single session would keep around 232 bytes for every stream that was closed?
From the nghttp2 docs, it seems
nghttp2_option_set_no_closed_streamsis only doingwhat other checks it is doing?
jasnell commentedon Sep 27, 2018
Ah, right, given that we're not really make use of priority, this likely can be switched off. Still, in this particular use case, I would still set a significantly higher
maxSessionMemory.davedoesdev commentedon Sep 27, 2018
If I increase
maxSessionMemoryto 100Mb, the server starts failing requests after 400k of them on a session.The Web page has no way of resetting its session with the server - the
fetchAPI has no way to tell the browser to use a new connection when the failures start (unless I've missed something).So this means long running sessions to Node over HTTP/2 don't work reliably.
jasnell commentedon Sep 27, 2018
Will investigate further! :)
http2: set nghttp2_option_set_no_closed_streams
http2: set nghttp2_option_set_no_closed_streams
http2: set nghttp2_option_set_no_closed_streams