Иди утечка горутин при использовании прокси - PullRequest
0 голосов
/ 15 мая 2018

Пожалуйста, помогите мне решить мою проблему.Я написал код для проверки прокси.В общем, я запускаю 50 процедур, каждая из которых затем получает прокси с канала и проверяет, работает ли она, и получает правильный ответ с моей тестовой страницы.Каждая программа создала это отношение

запрос ----> прокси ---> моя тестовая страница ---> тестирование содержимого с моей тестовой страницы.

функция проверки этого отношения:

    // GetAndCheckURL get test page via proxy and check its body.
func GetAndCheckURL(c *http.Client, urlStr string) ([]byte, error) {
    resp, err := c.Get(urlStr)
    if err != nil {
        return nil, fmt.Errorf("request error: %v", err)

    }
    defer func() {
        if err := resp.Body.Close(); err != nil {
            packageLogger.Neverf("can't close response body, error: %v", err)
        }
    }()
    if body, err := ioutil.ReadAll(resp.Body); err != nil {
        packageLogger.Neverf("Can't read response body, URL '%s', error: %v, response statusCode: %d, status: %s\n", urlStr, err, resp.StatusCode, resp.Status)
        return nil, err
    } else if !bytes.Contains(body, []byte("<!--proxy_test")) {
        return nil, errors.New("invalid body")
    } else {
        return body, nil
    }
}

Поскольку каждая подпрограмма проверяет различные прокси, я не могу использовать отдельные структуры http.Transport и http.Client.Эта функция GetAndCheckURL получает свой http.client со своим http.transport (с прокси). Эта функция выполняется в моих рабочих по этому коду :

    // readProxyWorker worker read proxy from chan.
func readProxyWorker(DB *storm.DB, workerNum int, conf config.CheckTaskConfig, ownIP string, proxyWaitChan <-chan proxy.Proxy, m proxy.CheckMetrics) {
    for i := 0; i < workerNum; i++ {
        go func() {
            var err error
            for p := range proxyWaitChan {
                // HERE RUN FUNCTION WHAT CHECK PROXIES
            }
        }()
    }
}

Но проблема в том, что для прокси socks5 у меня есть программы утечки.

 goroutine 160801 [IO wait, 915 minutes]:
internal/poll.runtime_pollWait(0x7fb2ab337410, 0x72, 0xc4206b96a8)
    /usr/local/Cellar/go/1.10.1/libexec/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc420c29998, 0x72, 0xffffffffffffff00, 0xb2e180, 0xe34418)
    /usr/local/Cellar/go/1.10.1/libexec/src/internal/poll/fd_poll_runtime.go:85 +0x9b
internal/poll.(*pollDesc).waitRead(0xc420c29998, 0xc422915e00, 0x2, 0x13)
    /usr/local/Cellar/go/1.10.1/libexec/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Read(0xc420c29980, 0xc422915ee0, 0x2, 0x13, 0x0, 0x0, 0x0)
    /usr/local/Cellar/go/1.10.1/libexec/src/internal/poll/fd_unix.go:157 +0x17d
net.(*netFD).Read(0xc420c29980, 0xc422915ee0, 0x2, 0x13, 0x0, 0x0, 0xe7c080)
    /usr/local/Cellar/go/1.10.1/libexec/src/net/fd_unix.go:202 +0x4f
net.(*conn).Read(0xc4214ec1b8, 0xc422915ee0, 0x2, 0x13, 0x0, 0x0, 0x0)
    /usr/local/Cellar/go/1.10.1/libexec/src/net/net.go:176 +0x6a
io.ReadAtLeast(0x7fb2ab62d868, 0xc4214ec1b8, 0xc422915ee0, 0x2, 0x13, 0x2, 0xa99f60, 0x0, 0x7fb2ab62d868)
    /usr/local/Cellar/go/1.10.1/libexec/src/io/io.go:309 +0x86
io.ReadFull(0x7fb2ab62d868, 0xc4214ec1b8, 0xc422915ee0, 0x2, 0x13, 0x0, 0x0, 0x0)
    /usr/local/Cellar/go/1.10.1/libexec/src/io/io.go:327 +0x58
vendor/golang_org/x/net/proxy.(*socks5).connect(0xc4208b6690, 0xb367c0, 0xc4214ec1b8, 0xc42083cd60, 0x11, 0xb367c0, 0xc4214ec1b8)
    /usr/local/Cellar/go/1.10.1/libexec/src/vendor/golang_org/x/net/proxy/socks5.go:113 +0x2f5
vendor/golang_org/x/net/proxy.(*socks5).Dial(0xc4208b6690, 0xabaa03, 0x3, 0xc42083cd60, 0x11, 0xc42083ce80, 0x12, 0xb367c0, 0xc4214ec1b8)
    /usr/local/Cellar/go/1.10.1/libexec/src/vendor/golang_org/x/net/proxy/socks5.go:75 +0xf3
net/http.(*Transport).dialConn(0xc420e1eff0, 0xb32400, 0xc420020078, 0xc420c29580, 0xc420024780, 0x5, 0xc42083cd60, 0x11, 0xae8d10, 0xc4229ee7b8, ...)
    /usr/local/Cellar/go/1.10.1/libexec/src/net/http/transport.go:1176 +0x6f7
net/http.(*Transport).getConn.func4(0xc420e1eff0, 0xb32400, 0xc420020078, 0xc421205a70, 0xc4209fa7e0)
    /usr/local/Cellar/go/1.10.1/libexec/src/net/http/transport.go:957 +0x78
created by net/http.(*Transport).getConn
    /usr/local/Cellar/go/1.10.1/libexec/src/net/http/transport.go:956 +0x363

    goroutine 18553 [chan receive, 27 minutes]:
net/http.(*Transport).getConn.func2.1(0x1a7c8900, 0x19b8ff40, 0x84f7388)
    /usr/local/go/src/net/http/transport.go:946 +0x41
created by net/http.(*Transport).getConn.func2
    /usr/local/go/src/net/http/transport.go:945 +0x61

И я не знаю, где моя ошибка.Я могу решить эту проблему только при добавлении срока для подключения (или ReadDeadline и WriteDeadline).Но я хочу решить мою проблему с таймаутами.Я пробую много вариантов таймаутов, но эта утечка существует.В моем http.Transport DisablekeepAlive верно, net.Dialer и http.Client имеют тайм-ауты.

Помогите, пожалуйста.

1 Ответ

0 голосов
/ 23 января 2019

У меня была похожая проблема, также была проблема с утечкой горутин. Первый был связан с тайм-аутом KeepAlive в Dialer, а другой - с TLSHandshakeTimeout. Иногда моя программа зависала. Следующий код должен помочь вам избежать этого. Надеюсь, это поможет вам)

&http.Transport{
        DialContext: (&net.Dialer{
            Timeout:   5 * time.Second,
            KeepAlive: 5 * time.Second,
            DualStack: true,
        }).DialContext,
        TLSHandshakeTimeout:   2 * time.Second,
        ResponseHeaderTimeout: 2 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
        DisableKeepAlives:     true,
    }
...