Перейдите http.Get, concurrency и "Connection reset by peer"

У меня есть между 1000-2000 веб-страниц для загрузки с одного сервера, и я использую подпрограммы и каналы для достижения высокой эффективности. Проблема в том, что каждый раз, когда я запускаю свою программу, до 400 запросов с ошибкой "connection reset by peer". Редко (возможно, 1 из 10 раз), запросы не выполняются.

Что я могу сделать, чтобы предотвратить это?

Интересно то, что когда я запускал эту программу на сервере в той же стране, что и сервер, на котором размещен сайт, 0 запросов не удалось, поэтому я предполагаю, что есть некоторая проблема с задержкой (как сейчас работающий на сервере на другом континенте).

Код, который я использую, - это просто простой запрос http.Get(url), никаких дополнительных параметров или пользовательский клиент.

Ответ 1

Сообщение connection reset by peer указывает, что удаленный сервер отправил RST, чтобы принудительно закрыть соединение, либо намеренно как механизм ограничения соединений, либо в результате нехватки ресурсов. В любом случае вы, вероятно, открываете слишком много соединений или слишком быстро пересоединяетесь.

Запуск 1000-2000 подключений является параллельным - это редко самый эффективный способ загрузки многих страниц, особенно если большинство или все они происходят с одного сервера. Если вы проверите пропускную способность, вы найдете оптимальный уровень concurrency, который намного ниже.

Вы также захотите установить Transport.MaxIdleConnsPerHost в соответствии с уровнем concurrency. Если MaxIdleConnsPerHost меньше ожидаемого количества одновременных подключений, соединения с сервером часто закрываются после запроса, а только для немедленного открытия снова - это значительно замедлит ваш прогресс и, возможно, достигнет ограничений на соединение, наложенных сервером.

Ответ 2

Все еще новичок голанг, надеюсь, это поможет.

var netClient = &http.Client{}

func init() {
    tr := &http.Transport{
        MaxIdleConns:       20,
        MaxIdleConnsPerHost:  20,
    }
    netClient = &http.Client{Transport: tr}
}

func foo() {
    resp, err := netClient.Get("http://www.example.com/")
}

Ответ 3

Возможно, сервер, с которого вы загружаете веб-страницы, имеет какой-то механизм дросселирования, который предотвращает более определенного количества запросов в секунду/(или подобных) от определенного ip?. Попытайтесь ограничить, возможно, 100 запросов в секунду или добавить спать между запросами. Соединение reset с помощью одноранговой сети - это в основном сервер, отрицающий ваш сервис. (Что такое " соединение reset by peer" означает?)

Ответ 4

Я добился хороших результатов, установив опцию MaxConnsPerHost на транспорте...

cl := &http.Client{
    Transport: &http.Transport{MaxConnsPerHost: 50}
}

MaxConnsPerHost опционально ограничивает общее количество подключений на хост, включая подключения в состоянии набора, активного и незанятого состояния. При нарушении лимита набор будет заблокирован.

https://golang.org/pkg/net/http/#Transport.MaxConnsPerHost

ОБНОВЛЕНИЕ: Чтобы уточнить, эта опция была выпущена в Go 1.11, который не был доступен во время ответов @AG1 или @JimB выше, поэтому я опубликовал это.