Перейдите 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 выше, поэтому я опубликовал это.