[go-nuts] HTTP2: Stream responses but with a write timeout
I'm confused about the current state of server timeouts being exposed by go1.17 for HTTP2 connections. With a TLS/HTTP2 server that is streaming responses to a client that has fetched and is in a readable stream loop, the stream stays up and the server sends data whenever it wants - for example once a second. My current tests are sending updates every second, like the http2 clockstream demo from years ago. But I also want to expose this server to the internet and enable the http.Server WriteTimeout property to guard against a client not consuming TCP data at normal pace. Right now it seems the http.Server WriteTimeout property is causing a timeout on the stream to expire, even though the client is consuming the TCP data with no delays. So the WriteTimeout property is acting as an HTTP2 stream timeout, having little to do with the actual write (and flush). Is there an established way of getting both? I have access to the underlying net.Conn. I've seen go1.18 will likely provide access to the underlying net.Conn and I've cherry picked that for my go1.17 build already. I guess I'm also confused by the rationale for the said timeout for HTTP2 connections. It doesn't seem like an underlying limitation of Linux that the timeout has to be applied to a request completing when some would just want individual writes or flushes to have timeouts. -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/26a67d12-cd1c-4b30-85cb-fa39c0c2a0fcn%40googlegroups.com.
[go-nuts] http2 WriteTimeout: Issue 49741 in go1.17.6 or not?
https://github.com/golang/go/issues/49741 x/net/http2: http.Server.WriteTimeout does not fire if the http2 stream's window is out of space. #49741 The 1.17 back port issue: x/net/http2: http.Server.WriteTimeout does not fire if the http2 stream's window is out of space. [1.17 backport] #49921 Loaded go1.17.6 on Mac and Linux machines. Saw the release notes say issue #49741 is cherry-picked as #49921. Looked at the issue and found a very concise hanging example and expected the example would no longer hang. But it hangs on both Mac and Linux. I admit to being confused by how the x/net/http2 source is being vendored. I did not find the source files in the go1.17.6 source tree created from the go1.17.6.tar.gz download. Here's the example @davecheney provided: ```go package main import ( "io" "log" "net/http" "net/http/httptest" "strings" "time" ) func handler(w http.ResponseWriter, r *http.Request) { data := strings.Repeat("x", 1<<16) tick := time.NewTicker(1 * time.Millisecond) defer tick.Stop() for { select { case <-tick.C: n, err := io.WriteString(w, data) log.Printf("wrote %d, err %v", n, err) if err != nil { return } case <-r.Context().Done(): log.Printf("context cancelled") return } } } func main() { sv := httptest.NewUnstartedServer(http.HandlerFunc(handler)) sv.EnableHTTP2 = true sv.Config.WriteTimeout = 1 * time.Second sv.StartTLS() resp, err := sv.Client().Get(sv.URL + "/") if err != nil { log.Fatal(err) } defer resp.Body.Close() select {} // block forever } ``` -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/5b003909-cdd6-4ede-a0ae-a990a5403716n%40googlegroups.com.
Re: [go-nuts] http2 WriteTimeout: Issue 49741 in go1.17.6 or not?
Sorry. I misrepresented the problem. The issue was that the example should print "wrote 4096, err http2: stream closed" after a second, having filled the buffer with 64 64KiB writes first. Even with go1.17.6, it doesn't do that. The 65th write is not timing out. But it does work if I use the recent golang.org/x/net. I see the http2 code is in h2_bundle.go and the cherry picked changes are in fact there, in the go1.17.6 tagged checkout. So the cherry-pick operation was done correctly. Maybe that cherry-pick was necessary but it appears it isn't sufficient. To get the intended behavior, the timeout after a second of being hung, I still have to require the golang.org/x/net from 20220127 and configure the server with it func main() { sv := httptest.NewUnstartedServer(http.HandlerFunc(handler)) err := http2.ConfigureServer(sv.Config, &http2.Server{}) if err != nil { log.Fatal(err) } // defer sv.Close() sv.EnableHTTP2 = true sv.Config.WriteTimeout = 1 * time.Second sv.StartTLS() resp, err := sv.Client().Get(sv.URL + "/") if err != nil { log.Fatal(err) } defer resp.Body.Close() select {} // block forever } My go.mod: module main go 1.17 require golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd require golang.org/x/text v0.3.7 // indirect On Friday, January 28, 2022 at 4:29:07 PM UTC-5 Ian Lance Taylor wrote: > On Fri, Jan 28, 2022 at 6:44 AM frankre...@gmail.com > wrote: > > > > https://github.com/golang/go/issues/49741 > > > > x/net/http2: http.Server.WriteTimeout does not fire if the http2 > stream's window is out of space. #49741 > > > > The 1.17 back port issue: > > x/net/http2: http.Server.WriteTimeout does not fire if the http2 > stream's window is out of space. [1.17 backport] #49921 > > > > Loaded go1.17.6 on Mac and Linux machines. Saw the release notes say > issue #49741 is cherry-picked as #49921. Looked at the issue and found a > very concise hanging example and expected the example would no longer hang. > But it hangs on both Mac and Linux. > > > > I admit to being confused by how the x/net/http2 source is being > vendored. I did not find the source files in the go1.17.6 source tree > created from the go1.17.6.tar.gz download. > > The x/net/http2 sources are bundled into the generated file > net/http/h2_bundle.go. > > > > Here's the example @davecheney provided: > > That program is always going to hang, because the main function never > returns. I'm not sure what the buggy behavior is here. > > Ian > -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/eba2dce6-97ea-483b-968c-6d415c801eb2n%40googlegroups.com.
Re: [go-nuts] http2 WriteTimeout: Issue 49741 in go1.17.6 or not?
I've narrowed down the difference between the case where it fails to timeout and where it does timeout to whether the http2 ConfigureServer is manually called on the *http.Server. I had to export the http2ConfigureServer in h2_bundle.go to be able to call it from the std http package but when I did, the timeout was honored. Without it, the timeout on the http2 stream doesn't happen. I've updated the issue #49741 although it is closed so I don't know if anyone will see it. On Saturday, January 29, 2022 at 10:52:56 AM UTC-5 frankre...@gmail.com wrote: > Sorry. I misrepresented the problem. The issue was that the example should > print "wrote 4096, err http2: stream closed" after a second, having filled > the buffer with 64 64KiB writes first. Even with go1.17.6, it doesn't do > that. The 65th write is not timing out. > > But it does work if I use the recent golang.org/x/net. > > I see the http2 code is in h2_bundle.go and the cherry picked changes are > in fact there, in the go1.17.6 tagged checkout. So the cherry-pick > operation was done correctly. Maybe that cherry-pick was necessary but it > appears it isn't sufficient. > > To get the intended behavior, the timeout after a second of being hung, I > still have to require the golang.org/x/net from 20220127 and configure > the server with it > > func main() { > sv := httptest.NewUnstartedServer(http.HandlerFunc(handler)) > err := http2.ConfigureServer(sv.Config, &http2.Server{}) > > if err != nil { > log.Fatal(err) > } > // defer sv.Close() > > sv.EnableHTTP2 = true > sv.Config.WriteTimeout = 1 * time.Second > sv.StartTLS() > > resp, err := sv.Client().Get(sv.URL + "/") > if err != nil { > log.Fatal(err) > } > defer resp.Body.Close() > > select {} // block forever > } > > My go.mod: > > module main > > go 1.17 > > require golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd > > require golang.org/x/text v0.3.7 // indirect > On Friday, January 28, 2022 at 4:29:07 PM UTC-5 Ian Lance Taylor wrote: > >> On Fri, Jan 28, 2022 at 6:44 AM frankre...@gmail.com >> wrote: >> > >> > https://github.com/golang/go/issues/49741 >> > >> > x/net/http2: http.Server.WriteTimeout does not fire if the http2 >> stream's window is out of space. #49741 >> > >> > The 1.17 back port issue: >> > x/net/http2: http.Server.WriteTimeout does not fire if the http2 >> stream's window is out of space. [1.17 backport] #49921 >> > >> > Loaded go1.17.6 on Mac and Linux machines. Saw the release notes say >> issue #49741 is cherry-picked as #49921. Looked at the issue and found a >> very concise hanging example and expected the example would no longer hang. >> But it hangs on both Mac and Linux. >> > >> > I admit to being confused by how the x/net/http2 source is being >> vendored. I did not find the source files in the go1.17.6 source tree >> created from the go1.17.6.tar.gz download. >> >> The x/net/http2 sources are bundled into the generated file >> net/http/h2_bundle.go. >> >> >> > Here's the example @davecheney provided: >> >> That program is always going to hang, because the main function never >> returns. I'm not sure what the buggy behavior is here. >> >> Ian >> > -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/e07ab828-f8a1-4fca-8aa3-4f7205d058ean%40googlegroups.com.