Java 11 HttpClient Http2 Too many streams Error
Unfortunately, the approach with Semaphore
, suggested by @sbordet, didn't work for me. I tried this:
var semaphore = semaphores.computeIfAbsent(getRequestKey(request), k -> new Semaphore(MAX_CONCURRENT_REQUESTS_NUMBER));
CompletableFuture.runAsync(semaphore::acquireUninterruptibly, WAITING_POOL)
.thenComposeAsync(ignored -> httpClient.sendAsync(request, responseBodyHandler), ASYNC_POOL)
.whenComplete((response, e) -> semaphore.release());
There's no guarantee that a connection stream is released by the time the execution is passed to the next CompletableFuture
, where the semaphore is released. For me the approach worked in case of normal execution, however if there're any exceptions, it seems that the connection stream may be closed after semaphore.release()
is invoked.
Finally, I ended up by using OkHttp. It handles the problem (it just waits until some streams are freed up if the number of concurrent streams reaches max_concurrent_streams
). It also handles the GOAWAY
frame. In case of Java HttpClient
I had to implement retry logic to handle this as it just throws IOException
if the server sends GOAWAY
frame.
When I try to hit the server continuously
The server has a setting for max_concurrent_streams
that is communicated to the client during the initial establishment of a HTTP/2 connection.
If you blindly "hit the server continuously" using sendAsync
you are not waiting for previous requests to finish and eventually you exceed the max_concurrent_streams
value and receive the error above.
The solution is to send concurrently a number of requests that is less than max_concurrent_streams
; after that, you only send a new request when a previous one completes.
This can easily implemented on the client using a Semaphore
or something similar.