Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Http 在Go中使用DialContext的性能问题_Http_Go - Fatal编程技术网

Http 在Go中使用DialContext的性能问题

Http 在Go中使用DialContext的性能问题,http,go,Http,Go,我使用Go的内置http.Client和net做了一个快速基准测试。与不使用相比,使用DialContext时会导致一些明显的性能问题 我基本上是在模仿我们公司的一个用例,在这个用例中,http.Client设置与默认配置相比,在完全用于相同的事情时,性能要差得多。我注意到对DialContext部分的注释使它运行得更快 基准测试只是打开一个线程池(本例中为8个)来创建到简单URL的连接,使用与线程数(8)相同大小的缓冲通道 以下是带有DialContext(2.266333805s)的代码:

我使用Go的内置
http.Client
net
做了一个快速基准测试。与不使用相比,使用
DialContext
时会导致一些明显的性能问题


我基本上是在模仿我们公司的一个用例,在这个用例中,
http.Client
设置与默认配置相比,在完全用于相同的事情时,性能要差得多。我注意到对
DialContext
部分的注释使它运行得更快

基准测试只是打开一个线程池(本例中为8个)来创建到简单URL的连接,使用与线程数(8)相同大小的缓冲通道

以下是带有
DialContext
(2.266333805s)的代码:

输出时间为731.154103ms

结果之间的差异在程序的多次运行中是一致的

有人知道为什么会这样吗

谢谢

编辑:因此我尝试了
net/http/httptrace
,并确保已完全读取并关闭了响应主体:

go func() {
    for range c {
        req, _ := http.NewRequest(http.MethodGet, url, nil)
        req = req.WithContext(httptrace.WithClientTrace(req.Context(), &httptrace.ClientTrace{
            GotConn: t.gotConn,
        }))
        resp, _ := httpClient.Do(req)
        ioutil.ReadAll(resp.Body)
        resp.Body.Close()
    }
    wg.Done()
}()
使用
DialContext
vs不使用它时的发现是有趣的

不使用拨号上下文:

time taken to run 200 requests: 5.639808793s
new connections: 1
reused connections: 199
time taken to run 200 requests: 5.682882723s
new connections: 8
reused connections: 192
使用拨号上下文:

time taken to run 200 requests: 5.639808793s
new connections: 1
reused connections: 199
time taken to run 200 requests: 5.682882723s
new connections: 8
reused connections: 192

它更快。。。但是为什么一个打开了8个新连接,而另一个只打开了1个?

获得如此大差异的唯一方法是,如果一个传输正在重用连接,而另一个没有。为了确保可以重用连接,必须始终读取响应正文。在某些情况下,连接可能会在不显式读取正文的情况下被重用,但这永远无法保证,这取决于许多事情,如远程服务器关闭连接、响应是否被
传输
完全缓冲,以及请求上是否存在上下文

该包可以让您深入了解许多请求内部,包括连接是否被重用。有关示例,请参见

设置
DisableKeepAlive
将始终阻止重新使用连接,从而使这两个连接都同样缓慢。总是这样读取响应将使两种响应速度相似:

req, _ := http.NewRequest(http.MethodGet, url, nil)
resp, err := httpClient.Do(req)
if err != nil {
    // handle error
    continue
}
io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close()

如果你想知道在断开连接之前可以读取多少数据,你可以简单地用一个

1)执行你的基准测试;2) 您正在调整
DialContext
中的几个设置,在另一个示例中,您将默认保留这些设置。您也根本没有检查响应。很可能在第一次运行后,您的连接因滥用而被拒绝。仅使用
DialContext:http.DefaultTransport时也会发生同样的情况。(*http.Transport)。DialContext
:(我基本上是在模仿我们公司的一个用例,
http.Client
设置在完全相同的情况下比默认配置的性能要差得多。我注意到对
DialContext
部分的注释使它运行得更快。@JimB我以不同的顺序尝试了好几次,还有部分e> DialContext总是比较慢。非常感谢。您建议使用
net/http/httptrace
表明您在重用连接方面是正确的。我还做了一些进一步的阅读,以确保响应正文总是被阅读。不过,我在帖子上添加了一个编辑部分来显示我的结果。介意看看吗?有显然,在初始请求调用的序列化方面存在一些差异,但最终这并不重要。您必须更深入地了解内部结构以了解原因,但单传输和客户端在并发请求速度方面还是有一定的限制。