transport: &http.Transport{ DialContext: proxy.DailContext, Proxy: func(req *http.Request) (*url.URL, error) { if proxyURL, ok := req.Context().Value(proxy.KeyProxyURL).(*url.URL); ok { return proxyURL, nil } return nil, nil }, TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, IdleConnTimeout: 15 * time.Second, ResponseHeaderTimeout: 10 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 10 * time.Second, MaxIdleConnsPerHost: 3, },}
附上 pprof 图,
http://img.aladdinding.cn/202304030947153.png
集中在 bufio NewReader/Writer 是什么原因呢?
pconn.br = bufio.NewReaderSize(pconn, t.readBufferSize()) pconn.bw = bufio.NewWriterSize(persistConnWriter{pconn}, t.writeBufferSize()) go pconn.readLoop() go pconn.writeLoop() return pconn, nil
![]() | 1 picone 2023-04-03 10:47:14 +08:00 有内存变化趋势图吗?看了一下由 dialConn 代码内调用的 bufio 就这俩地,看起来是连接池使用的? https://github.com/golang/go/blob/8edcdddb23c6d3f786b465c43b49e8d9a0015082/src/net/http/transport.go#L1769-L1770 |
![]() | 2 aladdinding OP @picone 是用了连接池,内存变化是缓慢增长,看 github 也是有一样的 issue ,但是也没讲出问题原因是什么 |
![]() | 3 Reficul 2023-04-03 11:41:44 +08:00 MaxIdleConns MaxIdleConnsPerHost MaxConnsPerHost 这几个参数改大点试试看 |
![]() | 4 picone 2023-04-03 11:42:38 +08:00 @aladdinding #2 你可以试试把连接池关闭了,验证是否就是连接池的问题。 另外你对外请求的 host 是多个的还是同一个? |
![]() | 5 lysS 2023-04-03 12:38:21 +08:00 1.5G 也叫内存泄漏吗?泄漏不是内存大,而是自增不减 |
![]() | 6 lysS 2023-04-03 12:43:29 +08:00 默认的那个 buff 是 4KB |
![]() | 7 zizon 2023-04-03 13:06:31 +08:00 如果 buf.New 泄露的话,对应的应该 goroutine 也应该增长的. transport.dialConnFor 是个 goroutine,看着是 req cancel 的时候会退出. 是请求多的时候有些没 cancel 掉导致? |
![]() | 8 sadfQED2 2023-04-03 13:10:33 +08:00 via Android 插眼,同样的全局 transport ,类似的问题,查了一年都没解决。现在是加监控自动重启。 |
![]() | 9 sadfQED2 2023-04-03 13:11:11 +08:00 via Android 楼主解决了记得分享下啊 |
![]() | 10 aladdinding OP @picone transport 加了 DisableKeepAlives:true 就没有内存泄漏了, 但是我看代码,加了后会在 header 加入 connection:close ,如果目标网站识别到 close ,主动关闭连接的话,就用不了长连接了 对外请求是很多郁闷,而且还有很多代理,通过 connectMethodKey 来看,连接池会有很多连接,但是我设置了 IdleConnTimeout 为 15s 了,应该也不会出现内存泄漏 |
![]() | 11 aladdinding OP @aladdinding 对外请求是很多域名+不同的 http 代理 |
![]() | 12 aladdinding OP @sadfQED2 加了 DisableKeepAlives:true 临时解决的 |
![]() | 13 aladdinding OP @Reficul MaxIdleConns MaxIdleConns 默认都是 0 ,没有限制的 |
![]() | 14 picone 2023-04-03 15:47:45 +08:00 @aladdinding #11 go 的连接池是按照 host 来计算 idle connection 的 |
![]() | 15 aladdinding OP ![]() @picone 准确的说还有 proxy // connectMethod is the map key (in its String form) for keeping persistent // TCP connections alive for subsequent HTTP requests. // // A connect method may be of the following types: // // connectMethod.key().String() Description // ------------------------------ ------------------------- // |http|foo.com http directly to server, no proxy // |https|foo.com https directly to server, no proxy // |https,h1|foo.com https directly to server w/o HTTP/2, no proxy // http://proxy.com|https|foo.com http to proxy, then CONNECT to foo.com // http://proxy.com|http http to proxy, http to anywhere after that // socks5://proxy.com|http|foo.com socks5 to proxy, then http to foo.com // socks5://proxy.com|https|foo.com socks5 to proxy, then https to foo.com // https://proxy.com|https|foo.com https to proxy, then CONNECT to foo.com // https://proxy.com|http https to proxy, http to anywhere after that type connectMethod struct { _ incomparable proxyURL *url.URL // nil for no proxy, else full proxy URL targetScheme string // "http" or "https" // If proxyURL specifies an http or https proxy, and targetScheme is http (not https), // then targetAddr is not included in the connect method key, because the socket can // be reused for different targetAddr values. targetAddr string onlyH1 bool // whether to disable HTTP/2 and force HTTP/1 } |
![]() | 16 Reficul 2023-04-03 16:26:01 +08:00 @aladdinding #13 MaxConnsPerHost 默认是 2 我记得好像,高并发情况下会打出来一堆连接 |
![]() | 17 6IbA2bj5ip3tK49j 2023-04-03 16:52:19 +08:00 试试 httpClient.CloseIdleConnections() |
![]() | 18 777777 2023-04-03 17:37:52 +08:00 再告诉你个 bug ,官方库 net/http 的 websocket 和 http/2 存在不会退出造成协程和内存泄露。 |
![]() | 19 777777 2023-04-03 17:40:47 +08:00 |
![]() | 20 sadfQED2 2023-04-03 18:39:31 +08:00 via Android @aladdinding emmm ,看来没办法,我们需要 keepalive |
![]() | 21 sadfQED2 2023-04-03 18:49:29 +08:00 |
![]() | 23 bigNewsMaker 2023-04-03 21:33:33 +08:00 1 |