golang get massive read tcp ip:port i/o timeout in ubuntu 14.04 LTS

ymdaylpp  于 2023-08-01  发布在  Go
关注(0)|答案(2)|浏览(137)

我写了一个Golang程序,在过去的几个月里在ubuntu12.04LTS上运行良好,直到我升级到14.04LTS
我的程序专注于发送HTTP请求,每秒发送大约2-10个HTTP请求。HTTP请求地址不同。
当问题发生时,首先,一些请求显示read tcp [ip]:[port]: i/o timeout,然后几分钟后所有请求都显示read tcp [ip]:[port]: i/o timeout,没有任何请求可以发送。

我重新启动程序,一切又恢复正常
我们所有的服务器(2台服务器)从12.04升级到14.04后都出现了这样的问题
我为每个请求创建新的goroutine
问题不是在同一时间间隔内出现,有时不是一天或两天出现,有时一小时内出现两次

Bellow是我请求HTTP地址的代码:

t := &http.Transport{
    Dial:            timeoutDial(data.Timeout),
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
//req := s.ParseReq(data)
req := data.convert2Request()
if req == nil {
    return
}

var resp *http.Response
if data.Redirect {
    c := &http.Client{
        Transport: t,
    }
    resp, err = c.Do(req)
} else {
    resp, err = t.RoundTrip(req)
}

data.updateTry()

r := s.ParseResp(data, resp, err)

字符串
updateTry:

func (d *SendData) updateTry() {
    d.Try++
    d.LastSend = time.Now()
}


超时拨号:

func timeoutDial(timeout int) func(netw, addr string) (net.Conn, error) {
    if timeout <= 0 {
        timeout = 10
    }
    return func(netw, addr string) (net.Conn, error) {
        deadline := time.Now().Add(time.Duration(timeout) * time.Second)
        c, err := net.DialTimeout(netw, addr, time.Second*time.Duration(timeout+5))
        if err != nil {
            return nil, err
        }
        c.SetDeadline(deadline)
        return c, nil
    }
}


而我的应对方式是:

func (s *Sender) ParseResp(data SendData, resp *http.Response, err error) (r Resp) {
    r = Resp{URL: data.URL}
    if err != nil {
        r.Err = err.Error()
    } else {
        r.HttpCode = resp.StatusCode
        r.Header = resp.Header
        r.URL = resp.Request.URL.String()
        defer resp.Body.Close()
        // we just read part of response and log it.
        reader := bufio.NewReader(resp.Body)
        buf := make([]byte, bytes.MinRead) // 512 byte
        for len(r.Body) < 1024 {           // max 1k
            var n int
            if n, _ = reader.Read(buf); n == 0 {
                break
            }
            r.Body += string(buf[:n])
        }
    }
    return
}


我还在/etc/sysctl.conf中找到了一个可以降低问题发生频率的设置:

net.core.somaxconn = 65535
net.netfilter.nf_conntrack_max = 655350
net.netfilter.nf_conntrack_tcp_timeout_established = 1200


我需要帮助来解决这个问题。
看起来是这样,但我看不到任何解决方案https://bugs.launchpad.net/juju-core/+bug/1307434

wvmv3b1j

wvmv3b1j1#

为了更明确地说明Not_a_Golfer和OneOfOne所说的内容,当您完成响应时,您需要关闭一直打开的连接(通过Body字段,该字段是一个io.ReadCloser)。因此,基本上,一个简单的方法是将与发出http请求有关的代码更改为:

var resp *http.Response
if data.Redirect {
    c := &http.Client{
        Transport: t,
    }
    resp, err = c.Do(req)
} else {
    resp, err = t.RoundTrip(req)
}
if err == nil {
    defer resp.Body.Close() // we need to close the connection
}

字符串

xkftehaa

xkftehaa2#

在没有看到timeoutDial的代码的情况下,我大胆地猜测,当您完成连接时,您不会关闭它。

相关问题