diff --git a/proxy/http/client.go b/proxy/http/client.go index eba4ee7b1..0e2175a62 100644 --- a/proxy/http/client.go +++ b/proxy/http/client.go @@ -8,6 +8,7 @@ import ( "net/http" "net/url" "sync" + "time" "golang.org/x/net/http2" @@ -79,14 +80,23 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter var user *protocol.MemoryUser var conn internet.Connection - mbuf, _ := link.Reader.ReadMultiBuffer() - len := mbuf.Len() - firstPayload := bytespool.Alloc(len) - mbuf, _ = buf.SplitBytes(mbuf, firstPayload) - firstPayload = firstPayload[:len] + var firstPayload []byte - buf.ReleaseMulti(mbuf) - defer bytespool.Free(firstPayload) + if reader, ok := link.Reader.(buf.TimeoutReader); ok { + // 0-RTT optimization for HTTP/2: If the payload comes within 50 ms, it can be + // transmitted together. Note we should not get stuck here, as the payload may + // not exist (considering to access MySQL database via a HTTP proxy, where the + // server sends hello to the client first). + if mbuf, _ := reader.ReadMultiBufferTimeout(50 * time.Millisecond); mbuf != nil { + mlen := mbuf.Len() + firstPayload = bytespool.Alloc(mlen) + mbuf, _ = buf.SplitBytes(mbuf, firstPayload) + firstPayload = firstPayload[:mlen] + + buf.ReleaseMulti(mbuf) + defer bytespool.Free(firstPayload) + } + } if err := retry.ExponentialBackoff(5, 100).On(func() error { server := c.serverPicker.PickServer()