mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
net/http: add HTTP2Config.StrictMaxConcurrentRequests
Add a field to HTTP2Config controlling how we behave when an HTTP/2 connection reaches its concurrency limit. This field will have no effect until golang.org/x/net/http2 is updated to make use of it, and h2_bundle.go is updated with the new http2 package. For #67813 Change-Id: Ic72a0986528abb21649f28e9fe7cf6e1236b388d Reviewed-on: https://go-review.googlesource.com/c/go/+/615875 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Nicholas Husin <nsh@golang.org> Reviewed-by: Nicholas Husin <husin@google.com>
This commit is contained in:
parent
16be34df02
commit
3a5df9d2b2
4 changed files with 57 additions and 2 deletions
1
api/next/67813.txt
Normal file
1
api/next/67813.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
pkg net/http, type HTTP2Config struct, StrictMaxConcurrentRequests bool #67813
|
||||
4
doc/next/6-stdlib/99-minor/net/http/67813.md
Normal file
4
doc/next/6-stdlib/99-minor/net/http/67813.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
The new
|
||||
[HTTP2Config.StrictMaxConcurrentRequests](/pkg/net/http#HTTP2Config.StrictMaxConcurrentRequests)
|
||||
field controls whether a new connection should be opened
|
||||
if an existing HTTP/2 connection has exceeded its stream limit.
|
||||
|
|
@ -235,10 +235,23 @@ type Pusher interface {
|
|||
// both [Transport] and [Server].
|
||||
type HTTP2Config struct {
|
||||
// MaxConcurrentStreams optionally specifies the number of
|
||||
// concurrent streams that a peer may have open at a time.
|
||||
// concurrent streams that a client may have open at a time.
|
||||
// If zero, MaxConcurrentStreams defaults to at least 100.
|
||||
//
|
||||
// This parameter only applies to Servers.
|
||||
MaxConcurrentStreams int
|
||||
|
||||
// StrictMaxConcurrentRequests controls whether an HTTP/2 server's
|
||||
// concurrency limit should be respected across all connections
|
||||
// to that server.
|
||||
// If true, new requests sent when a connection's concurrency limit
|
||||
// has been exceeded will block until an existing request completes.
|
||||
// If false, an additional connection will be opened if all
|
||||
// existing connections are at their limit.
|
||||
//
|
||||
// This parameter only applies to Transports.
|
||||
StrictMaxConcurrentRequests bool
|
||||
|
||||
// MaxDecoderHeaderTableSize optionally specifies an upper limit for the
|
||||
// size of the header compression table used for decoding headers sent
|
||||
// by the peer.
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func TestTransportPoolConnCannotReuseConnectionInUse(t *testing.T) {
|
|||
|
||||
// When an HTTP/2 connection is at its stream limit
|
||||
// a new request is made on a new connection.
|
||||
func TestTransportPoolConnHTTP2OverStreamLimit(t *testing.T) {
|
||||
func testTransportPoolConnHTTP2NoStrictMaxConcurrentRequests(t *testing.T) {
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
dt := newTransportDialTester(t, http2Mode, func(srv *http.Server) {
|
||||
srv.HTTP2 = &http.HTTP2Config{
|
||||
|
|
@ -100,6 +100,43 @@ func TestTransportPoolConnHTTP2OverStreamLimit(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
// When an HTTP/2 connection is at its stream limit
|
||||
// and StrictMaxConcurrentRequests = true,
|
||||
// a new request waits for a slot on the existing connection.
|
||||
func TestTransportPoolConnHTTP2StrictMaxConcurrentRequests(t *testing.T) {
|
||||
t.Skip("skipped until h2_bundle.go includes support for StrictMaxConcurrentRequests")
|
||||
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
dt := newTransportDialTester(t, http2Mode, func(srv *http.Server) {
|
||||
srv.HTTP2.MaxConcurrentStreams = 2
|
||||
}, func(tr *http.Transport) {
|
||||
tr.HTTP2 = &http.HTTP2Config{
|
||||
StrictMaxConcurrentRequests: true,
|
||||
}
|
||||
})
|
||||
|
||||
// First request dials an HTTP/2 connection.
|
||||
rt1 := dt.roundTrip()
|
||||
c1 := dt.wantDial()
|
||||
c1.finish(nil)
|
||||
rt1.wantDone(c1, "HTTP/2.0")
|
||||
|
||||
// Second request uses the existing connection.
|
||||
rt2 := dt.roundTrip()
|
||||
rt2.wantDone(c1, "HTTP/2.0")
|
||||
|
||||
// Third request blocks waiting for a slot on the existing connection.
|
||||
rt3 := dt.roundTrip()
|
||||
|
||||
// First request finishing unblocks the thirrd.
|
||||
rt1.finish()
|
||||
rt3.wantDone(c1, "HTTP/2.0")
|
||||
|
||||
rt2.finish()
|
||||
rt3.finish()
|
||||
})
|
||||
}
|
||||
|
||||
// A new request made while an HTTP/2 dial is in progress will start a second dial.
|
||||
func TestTransportPoolConnHTTP2Startup(t *testing.T) {
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue