: panic: Get http:/-6ren">
gpt4 book ai didi

sockets - 多个 http.Requests 给出 "can' t 分配请求的地址,“除非加速

转载 作者:IT王子 更新时间:2023-10-29 02:27:52 24 4
gpt4 key购买 nike

使用下面的客户端代码(以及此框上端口 8088 上的监听 Web 服务器),在 client.Get() 弹出此错误之前,我很少能够获得超过 23000 次点击>:

panic: Get http://localhost:8088/: dial tcp 127.0.0.1:8088: can't assign requested address

奇怪的是,如果我增加计时器延迟(即从一毫秒到一微秒),则需要更多的点击才能出现错误,170,000 甚至更多。

查看网络流量,每个客户端连接在断开连接之前只使用了几次(即客户端发送 FIN)。很明显,它建立了许多 TCP 连接并溢出了套接字表。鉴于 Golang HTTP 文档说默认情况下启用保活,我不希望这样。内核跟踪显示底层套接字在关闭之前没有发出任何错误(除了 EAGAIN,这是预期的,并不总是在套接字关闭之前)。

这是 OSX (14.4.0) 上的 Go 1.4.2。为什么客户端连接没有一直被重用?

package main

import (
"io/ioutil"
"net/http"
"runtime"
"sync"
"time"
)

var reqnum = 0

func hit(client *http.Client) {
resp, err := client.Get("http://localhost:8088/")
if err != nil {
println(reqnum)
panic(err)
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
reqnum++ // not thread safe, but shouldn't cause errors.
}

func main() {
var wg sync.WaitGroup
runtime.GOMAXPROCS(runtime.NumCPU())
client := &http.Client{}
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
ticker := time.NewTicker(time.Microsecond * 1000)
for j := 0; j < 120000; j++ {
<-ticker.C
hit(client)
}
ticker.Stop()
}()
}
wg.Wait()
}

最佳答案

错误 can't assign requested address during a Dial 是由用于客户端连接的本地临时端口用完引起的。您用完端口的原因仅仅是因为您建立的连接太多,速度太快。当您加快连接速率时会发生什么,您开始捕获空闲连接在它们关闭之前返回到池中。有一个代码路径可以在 Dial 期间捕获这些新的空闲连接以更快地返回连接,但是没有办法每次都确定地捕获这些连接。

由于您只连接到一台主机(如评论中所述),您需要做的是将 Transport.MaxIdleConnsPerHost 设置得更高。您需要查看它在哪里平衡,在太多打开的连接之间,以及何时开始过快地回收它们。

在客户端有一个信号量甚至可能是有利的,以防止同时连接过多,这会开始导致连接再次过快地回收。

关于sockets - 多个 http.Requests 给出 "can' t 分配请求的地址,“除非加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31800692/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com