Please test Go's HTTP/2 support

2,098 views
Skip to first unread message

Brad Fitzpatrick

unread,
Nov 7, 2015, 11:36:01 AM11/7/15
to golang-nuts
At Go tip (what will become Go 1.6), there is now support for HTTP/2, for both client and server.

If you run an HTTPS webserver (ListenAndServeTLS), or use the net/http client functionality for accessing HTTPS URLS (e.g. almost all web APIs), I would love feedback on the new HTTP/2 client & server code.

Please build Go tip and do tests. (I don't recommend running Go tip in production in general, unless you're careful)

Note that HTTP/2 is only by default on the http.DefaultTransport. If you make your own &http.Transport{...}, then you don't get HTTP/2, at least for now.

Both successful reports and bug reports are useful. And any observed performance/CPU/RAM/whatever changes.

Thanks in advance for any feedback!

Shawn Milochik

unread,
Nov 7, 2015, 2:31:41 PM11/7/15
to golang-nuts
Is this the best resource for building Go tip?

I'm very excited about playing with HTTP/2, and I suspect plenty of people are who wouldn't normally build Go from source. If there are any other tips we might need beyond what is here?

For example, if we want to stick with our stable version of Go but still play with tip on the same laptop, is it just a matter of changing PATH so a different version of Go is used?

As a side note, I recently learned of direnv (http://direnv.net/), which looks like it can be helpful here. Have others found success or stress trying to use it?

andrewc...@gmail.com

unread,
Nov 7, 2015, 4:16:43 PM11/7/15
to golang-nuts, Sh...@milochik.com
My advice to people is to not mess around with GOROOT. For most people it just causes problems. All you need to do is swap your $PATH to have gobuildir/bin/. You will need a version of go1.4 in the bootstrap path though (read the 1.5 release notes for instructions). I have never tried to build go from source on windows though so can't give advice there.

Brad Fitzpatrick

unread,
Nov 7, 2015, 6:58:07 PM11/7/15
to Sh...@milochik.com, golang-nuts
For now I recommend only people familiar with installing from tip help test at this point. There will be beta releases out later that are more stable and easier to test with.

But if you want a fun little project, it could be fun to follow those instructions. I agree with Andrew: no need to modify your GOROOT. Just use the right "go" binary when using the tip version.

e.g.
$ cd $HOME
$ cd gotip/src
$ ./make.bash  (or ./all.bash)

Then, from anywhere else:

$ $HOME/gotip/bin/go install ....
$ $HOME/gotip/bin/go bin ....



--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ibrahim M. Ghazal

unread,
Nov 9, 2015, 8:39:37 AM11/9/15
to Brad Fitzpatrick, golang-nuts
Is Server Push support on the roadmap for 1.6 or will it be delayed to
a later version?

Brad Fitzpatrick

unread,
Nov 9, 2015, 8:49:00 AM11/9/15
to Ibrahim M. Ghazal, golang-nuts

Later version.

Michael Banzon

unread,
Nov 9, 2015, 9:19:36 AM11/9/15
to Brad Fitzpatrick, Ibrahim M. Ghazal, golang-nuts
fwiw - shouldn't the push support be an actual server/application implementation feature rather than in the library?

I can't see a way for the current .ListenAndServeTLS to know what is good resources to force on connected clients.

--

Brad Fitzpatrick

unread,
Nov 9, 2015, 9:28:02 AM11/9/15
to Michael Banzon, golang-nuts, Ibrahim M. Ghazal

All such design questions are why said APIs will not arrive immediately in Go 1.6.

There are proposed changes to add API but they're not even being discussed at this point because we're focusing on getting sure the basics are sound.

Michael Banzon

unread,
Nov 9, 2015, 9:46:15 AM11/9/15
to Brad Fitzpatrick, golang-nuts, Ibrahim M. Ghazal

Noted.

HTTP2 in the std lib is really great news in itself!

(comedic comment of the day: the community is fast, I just saw a guy here at dotGo talking about this!!)

Leonel Quinteros

unread,
Nov 9, 2015, 9:50:54 AM11/9/15
to golang-nuts
This is great! 

I have a VM running FreeBSD 10 that i use to play with stuff like this. 
I'm having troubles building the gotip master branch, but i was able to successfully compile the go1.4 tag, am i doing something wrong? 

My steps: 

$ cd $HOME
$ git clone https://go.googlesource.com/go gotip
$ cp -rf gotip go1.4
$ cd go1.4
$ git checkout go1.4
$ cd src
$ ./all.bash

That worked just fine.

$ cd ../../gotip/src
$ ./all/bash

// It fails with a lot of errors like: 
/home/leo/gotip/src/runtime/zruntime_defs_freebsd_amd64.go:7: _Gidle redeclared in this block
previous declaration found at /home/leo/gotip/src/runtime/runtime2.go:18

Any help it's appreciated. 

I know Brad recommended this just for "experienced" gotip users, but i liked this little fun project and experience is earned this way though. 

Thanks all! 

Brad Fitzpatrick

unread,
Nov 9, 2015, 9:52:17 AM11/9/15
to Michael Banzon, golang-nuts, Ibrahim M. Ghazal

That was me. :-)

Slides: https://golang.org/s/http2iscoming

But I'm 90% sure you're joking.

Michael Banzon

unread,
Nov 9, 2015, 9:56:29 AM11/9/15
to Brad Fitzpatrick, golang-nuts, Ibrahim M. Ghazal

I am/was ;o)

I've seen enough videos with you (and Andrew) to recognize you in my sleep. ;-)

Oleku Konko

unread,
Nov 14, 2015, 4:15:26 PM11/14/15
to golang-nuts

Looking good so far ... would continue testing anyway  ... well done ... 

Matt Joiner

unread,
Dec 24, 2015, 4:26:59 AM12/24/15
to golang-nuts
Is there support yet for using HTTP2 on non-default transports? If not, how can I do this using external packages? Cheers

Brad Fitzpatrick

unread,
Dec 24, 2015, 11:37:31 AM12/24/15
to Matt Joiner, golang-nuts
For client-side, yes, See https://godoc.org/golang.org/x/net/http2#Transport and https://godoc.org/golang.org/x/net/http2#Transport.NewClientConn etc.

For server-side, not yet. We would need to export some bits.

It would help if I knew your actual use case, though.


Matt Joiner

unread,
Dec 25, 2015, 9:39:19 PM12/25/15
to golang-nuts

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/1ggSbDA_XYI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Brad Fitzpatrick

unread,
Dec 26, 2015, 1:14:55 AM12/26/15
to Matt Joiner, golang-nuts

http2 only does https, not http.

You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.

Mauro Trajber

unread,
Dec 29, 2015, 12:32:21 PM12/29/15
to golang-nuts
How can I multiplex multiple requests on the same http2 connection?

Is the client behavior changed? Must I still close the resp.Body to be able to re-use the persistent TCP connection even with http2?

I've wrote a simple test that spawns multiple goroutines that uses the same http client but requests are not being multiplexed - even closing resp.Body.

This behavior looks very similar with http1.1 despite the fact that sending a single request the header 'HTTP/2.0' is present - so http2 is enabled.

Brad Fitzpatrick

unread,
Dec 29, 2015, 12:38:08 PM12/29/15
to Mauro Trajber, golang-nuts
On Tue, Dec 29, 2015 at 9:32 AM, Mauro Trajber <tra...@gmail.com> wrote:
How can I multiplex multiple requests on the same http2 connection?

It's automatic.
 
Is the client behavior changed? Must I still close the resp.Body to be able to re-use the persistent TCP connection even with http2?

No, you don't need to close the resp.Body to reuse the connection for http2, but you still need to close it to release resources. You may leak memory or goroutines if you don't close them, though, especially if you don't read to EOF.
 
I've wrote a simple test that spawns multiple goroutines that uses the same http client but requests are not being multiplexed - even closing resp.Body.

This behavior looks very similar with http1.1 despite the fact that sending a single request the header 'HTTP/2.0' is present - so http2 is enabled.

The string "HTTP/2.0" is never sent in http2. Where do you see that?

Can you share your code?

Mauro Romano Trajber

unread,
Dec 29, 2015, 12:47:08 PM12/29/15
to Brad Fitzpatrick, golang-nuts
Sure, here goes my code:


The string "HTTP/2.0" was printed when I use httputil.DumpResponse, maybe there's some special handling for http2 responses on this function - I didn't see the code yet.

Brad Fitzpatrick

unread,
Dec 29, 2015, 12:55:13 PM12/29/15
to Mauro Romano Trajber, golang-nuts
In your server, write back req.Proto and req.RemoteAddr to the ResponseWriter.

They should all have the same RemoteAddr and say HTTP/2.0 (yes, that is synthesized)

Brad Fitzpatrick

unread,
Dec 29, 2015, 1:00:08 PM12/29/15
to Mauro Romano Trajber, golang-nuts
Here's a counterexample that shows Go's http2 Transport code is working: http://play.golang.org/p/yVTPRr8X-O

It does 50 concurrent requests to https://http2.golang.org/reqinfo (whose response includes the RemoteAddr) and compares that all 5 responses are byte-for-byte identical.

Mauro Romano Trajber

unread,
Dec 29, 2015, 1:23:14 PM12/29/15
to Brad Fitzpatrick, golang-nuts
Thanks, Brad.

Instead writing back req.RemoteAddr to ResponseWriter I just log it on server log.

I've changed my test scenario a little bit: now only 1.000 goroutines are spawned and I don't know why but the client uses 3 different sockets:

    507 calls using 127.0.0.1:34566
    191 calls using 127.0.0.1:34637
    302 calls using 127.0.0.1:35172




Mauro Romano Trajber

unread,
Dec 29, 2015, 1:38:23 PM12/29/15
to Brad Fitzpatrick, golang-nuts
I've changed my test again: now I'm sending only 10 requests. All req.RemoteAddr are the same but netstat prints 10 different ports. The netstat output is attached.
netstat.txt

Brad Fitzpatrick

unread,
Dec 29, 2015, 1:47:10 PM12/29/15
to Mauro Romano Trajber, golang-nuts
The transport respects the server's advertised max configured streams.

Relevant code:

func (cc *ClientConn) canTakeNewRequestLocked() bool {
        return cc.goAway == nil &&
                int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
                cc.nextStreamID < 2147483647
}

Perhaps the http2 transport should just block goroutines until streams are available, though. I filed https://github.com/golang/go/issues/13774 to think about it later.


Mauro Romano Trajber

unread,
Dec 29, 2015, 2:17:20 PM12/29/15
to Brad Fitzpatrick, golang-nuts
Thanks again, Brad.

Reading the code I realize that the http2defaultMaxStreams is 250 if http2Server.MaxConcurrentStreams is zero and there's no way to change it using the http package. Do you have any plans to expose this configuration to the user?

Besides that, do you know why the netstat output is printing that the system is using different ports while req.RemoteAddr is printing always the same port?




Brad Fitzpatrick

unread,
Dec 29, 2015, 2:21:20 PM12/29/15
to Mauro Romano Trajber, golang-nuts
On Tue, Dec 29, 2015 at 11:16 AM, Mauro Romano Trajber <tra...@gmail.com> wrote:
Thanks again, Brad.

Reading the code I realize that the http2defaultMaxStreams is 250 if http2Server.MaxConcurrentStreams is zero and there's no way to change it using the http package. Do you have any plans to expose this configuration to the user?

See http://tip.golang.org/doc/go1.6#http2 ... "Programs that must adjust HTTP/2 protocol-specific details can import and use golang.org/x/net/http2"
 
Besides that, do you know why the netstat output is printing that the system is using different ports while req.RemoteAddr is printing always the same port?

I kinda suspect you're using the wrong version of Go or reading something wrong.


Mauro Romano Trajber

unread,
Dec 29, 2015, 3:01:44 PM12/29/15
to Brad Fitzpatrick, golang-nuts
I re-checked go version and netstat output and, honestly, I can't find the problem. 

go version go1.6beta1 linux/amd64

The server now sleeps 1 sec before writing back the response and prints req.RemoteAddr. All remote addresses are the same.

The client sends 10 concurrent requests and sleeps 10 secs so I have enough time to run netstat.

$> netstat -atpn | grep 12345
And netstat shows 10 different client ports being used (connection established)

Brad Fitzpatrick

unread,
Dec 29, 2015, 3:19:13 PM12/29/15
to Mauro Romano Trajber, golang-nuts
Email me a pcap file recording the traffic?

Mauro Romano Trajber

unread,
Dec 30, 2015, 7:18:24 AM12/30/15
to Brad Fitzpatrick, golang-nuts
The pcap file is attached. As you can see 10 different ports was used despite the log shows only one port.
gohttp2.pcap

Andy Balholm

unread,
Jan 4, 2016, 12:13:46 PM1/4/16
to Brad Fitzpatrick, golang-nuts
I’ve been working on HTTP/2 support in github.com/andybalholm/redwood. (It’s not merged into master yet; it’s on the http2 branch.) 

Due to the complexity of what I’m doing there, it took more that just recompiling with Go 1.6 beta. But it took only about a day of work to get a working HTTP/2 proxy, complete with translation to and from HTTP/1.1. I think that’s pretty amazing. Keep up the good work!

Andy
Reply all
Reply to author
Forward
0 new messages