supercombination
supercombination

Reputation: 47

Appropriate MAX_CONCURRENT_STREAMS value of http2

I have a situation where I need to set the max_concurrent_streams option while using grpc-go. So I read this RFC7540 document.

I read the article and searched, but I have a question that remains unanswered.

  1. I am trying to set MAX_CONCURRENT_STREAMS to uint64 max. Will there be any problems with this?
  2. If there is a problem when CONCURRENT_STREAM increases, what kind of problem is it?
  3. If there is no problem, why the default value of 100?

Upvotes: 3

Views: 12606

Answers (1)

sbordet
sbordet

Reputation: 18597

HTTP/2 has been designed, if you pardon my simplification, mostly to improve the browsing experience.

Web pages grow richer and HTTP/1.1 forced a number of "tricks" to overcome the fact that a single page could reference tens of other resources on the same domain -- think of *.css, *.js, *.png, etc. Download index.html, and then the browser has to make another 10-60 requests to download the dependent resources referenced by index.html.

With that in mind, HTTP/2's max_concurrent_streams is much larger than 6-8 (the parallelism that HTTP/1.1 could achieve) but obviously does not need to be 2^32-1. The value 100 is a good approximation of a max value for the current web pages.

It's not clear if you "have to set max_concurrent_streams" just because it's required, but the value does not matter much, as long as it is a sane value and you want to understand it better.

Or if you have to set it to to particular values, perhaps even dynamically, because that is what your application requires, so the value does matter.

Either case, 2^32-1 is not a good value, as it is an easy attack vector for evil clients. They will open a connection, see that your server allows 2^32-1 streams, and force the creation of these many streams, likely blowing up the server's memory. And if one connection is not enough to blow up the server, they will open many more connections, and for each connection 2^32-1 streams. Not good.

Also, as HTTP/2 is a multiplexed protocol, it requires flow control. HTTP/2 defines a connection flow control window, and a stream flow control window. The stream flow control window taps into the connection flow control window.

This means that a small max_concurrent_streams value allows each stream to use a larger portion of the connection flow control window for downloads (from server to client). This may be a good configuration for a file server where each client does not do many concurrent downloads.

Conversely, a large max_concurrent_streams value allows for more concurrent requests, but smaller per-stream flow-control windows. This may be a good configuration for a web pages server, where many resources should be served concurrently, but they are likely rather small.

gRPC being a generic RPC protocol does not typically require, like a web page does, requesting many dependent small resources concurrently; therefore the max_concurrent_streams value of a gRPC server is typically dictated by application-specific factors.

In summary there is no exact answer: you have to measure and see, or you have to know how your application works.

If you know that a single client will never make concurrent gRPC requests, then you can leave a default value of 100, or at the opposite reduce it to 1. The only stream that will ever be present in that connection will be able to tap into the whole connection flow control window (unless the stream is configured with a smaller per-stream flow control window).

If you know that a single client will make concurrent gRPC requests, you will have to know or measure how many, and how much data will be exchanged, and tune for that.

I would start with everything at default, monitor the server and see how it works. It may be that the default values are just fine and there is nothing that you have to do.

Upvotes: 10

Related Questions