K6: Any way to force to use HTTP/1.1 protocol

Created on 3 Mar 2019  路  5Comments  路  Source: loadimpact/k6

Just looked over the docs and didn't find any way to force the k6 not to switch to HTTP 2

I must do it cause we have a clients that won't use HTTP 2, so when I test I want to test the same protocol.

Tnx.

enhancement evaluation needed help wanted

Most helpful comment

A quick test with GODEBUG=http2client=0 and this script:

import http from "k6/http";

export default function () {
    let resp = http.get("https://google.com/");
    console.log(resp.proto);
}

shows that we unfortunately don't honor those environment variables. I think the reason is that line I quoted above: https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L171
We use that code from the golang.org/x/net/http2 package (connected k6 issue) because we define our own http.Transport just above that line: https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L153-L171
We need to define our own http.Transport in order to have customizable TLS settings, and we need to use http2.ConfigureTransport(transport) in order for that transport to support HTTP/2 at all. But it seems that in golang.org/x/net/http2 they don't honor any of the GODEBUG values besides http2debug: https://github.com/golang/net/search?q=GODEBUG&unscoped_q=GODEBUG :disappointed: So we'll need to handle disabling HTTP/2 in k6, and unfortunately it doesn't look like there's a quick workaround.

All 5 comments

Unfortunately there's currently no way to force k6 to use HTTP/1.1 if the remote server supports HTTP/2 and the connection is over HTTPS. I think that's mostly a consequence of the way the Go standard library's HTTP client operates - it also doesn't allow us to specify the HTTP version you want to use for a particular request.

That said, I think we can potentially slightly ameliorate this in k6 by adding the option to disable HTTP/2 globally, or at maybe at a per-VU/per-group() basis. Not sure how much refactoring would be needed for the more granular approaches, but the way we can do this is by modifying the http.Transport we use to make HTTP requests in k6. If we don't execute this line:
https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L171
k6 will be unable to make HTTP/2 requests. The trouble comes from the fact that this is executed once, in the beginning of initializing each VU, so it'd be somewhat difficult to get more granular than a global "don't allow any HTTP/2 requests" option...

Thanks for the answer.

Disallowing http/2 usage globally should be good enough. Cannot think about situation when I would like to test both protocols in the same benchmark session.

Just found in the go's doc:

Starting with Go 1.6, the http package has transparent support for the
HTTP/2 protocol when using HTTPS. Programs that must disable HTTP/2
can do so by setting Transport.TLSNextProto (for clients) or
Server.TLSNextProto (for servers) to a non-nil, empty
map. Alternatively, the following GODEBUG environment variables are
currently supported:

GODEBUG=http2client=0  # disable HTTP/2 client support
GODEBUG=http2server=0  # disable HTTP/2 server support
GODEBUG=http2debug=1   # enable verbose HTTP/2 debug logs
GODEBUG=http2debug=2   # ... even more verbose, with frame dumps

Before talking about refactoring, will the k6 see honor the GO's env variables? May be it can be a quick win...

A quick test with GODEBUG=http2client=0 and this script:

import http from "k6/http";

export default function () {
    let resp = http.get("https://google.com/");
    console.log(resp.proto);
}

shows that we unfortunately don't honor those environment variables. I think the reason is that line I quoted above: https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L171
We use that code from the golang.org/x/net/http2 package (connected k6 issue) because we define our own http.Transport just above that line: https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L153-L171
We need to define our own http.Transport in order to have customizable TLS settings, and we need to use http2.ConfigureTransport(transport) in order for that transport to support HTTP/2 at all. But it seems that in golang.org/x/net/http2 they don't honor any of the GODEBUG values besides http2debug: https://github.com/golang/net/search?q=GODEBUG&unscoped_q=GODEBUG :disappointed: So we'll need to handle disabling HTTP/2 in k6, and unfortunately it doesn't look like there's a quick workaround.

Understood. Tnx for help.

Will try for to fork k6 and implement it for my usage... if it will look good will open PR.

A proposal on how something like this (among other things) could be implemented in k6 in a backwards compatible and reasonably performant and user-friendly way: https://github.com/loadimpact/k6/issues/1045#issuecomment-501150436

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sdhoward picture sdhoward  路  3Comments

StephenRadachy picture StephenRadachy  路  3Comments

jrm2k6 picture jrm2k6  路  4Comments

caalle picture caalle  路  4Comments

git001 picture git001  路  3Comments