UPSTREAM: 67957: Size http2 buffers to allow concurrent streams
@@ -87,10 +87,30 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
secureServer.TLSConfig.ClientCAs = s.ClientCA
}
+ // At least 99% of serialized resources in surveyed clusters were smaller than 256kb.
+ // This should be big enough to accommodate most API POST requests in a single frame,
+ // and small enough to allow a per connection buffer of this size multiplied by `MaxConcurrentStreams`.
+ const resourceBody99Percentile = 256 * 1024
+
+ http2Options := &http2.Server{}
+
+ // shrink the per-stream buffer and max framesize from the 1MB default while still accommodating most API POST requests in a single frame
+ http2Options.MaxUploadBufferPerStream = resourceBody99Percentile
+ http2Options.MaxReadFrameSize = resourceBody99Percentile
+
+ // use the overridden concurrent streams setting or make the default of 250 explicit so we can size MaxUploadBufferPerConnection appropriately
if s.HTTP2MaxStreamsPerConnection > 0 {
- http2.ConfigureServer(secureServer, &http2.Server{
- MaxConcurrentStreams: uint32(s.HTTP2MaxStreamsPerConnection),
- })
+ http2Options.MaxConcurrentStreams = uint32(s.HTTP2MaxStreamsPerConnection)
+ } else {
+ http2Options.MaxConcurrentStreams = 250
+ }
+
+ // increase the connection buffer size from the 1MB default to handle the specified number of concurrent streams
+ http2Options.MaxUploadBufferPerConnection = http2Options.MaxUploadBufferPerStream * int32(http2Options.MaxConcurrentStreams)
+
+ // apply settings to the server
+ if err := http2.ConfigureServer(secureServer, http2Options); err != nil {
+ return fmt.Errorf("error configuring http2: %v", err)
}
glog.Infof("Serving securely on %s", secureServer.Addr)
