Сервис делает запросы во внешнее API, которое начало отвечать по 10 секунд. Горутины копятся, память растёт, сервис падает по OOM. Как защитить?
Ответ от нейросети
sobes.tech AI
Проблема в том, что горутины блокируются на долгих запросах к внешнему API, что приводит к накоплению горутин и росту потребления памяти.
Как защитить сервис:
-
Ограничить количество одновременно выполняющихся запросов — использовать семафор или пул воркеров, чтобы не создавать слишком много горутин.
-
Установить таймауты на HTTP-запросы — использовать контекст с таймаутом (
context.WithTimeout) или настроить таймауты в HTTP-клиенте, чтобы запросы не висели бесконечно. -
Обрабатывать ошибки и отменять запросы при таймауте — чтобы горутины не блокировались.
-
Использовать контекст для отмены запросов — передавать
context.Contextв функции, чтобы можно было отменить запрос при необходимости.
Пример с таймаутом и ограничением количества одновременных запросов:
var semaphore = make(chan struct{}, 10) // максимум 10 одновременных запросов
func callExternalAPI(ctx context.Context, url string) error {
semaphore <- struct{}{} // захватить слот
defer func() { <-semaphore }() // освободить слот
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// обработка ответа
return nil
}
Такой подход предотвратит накопление горутин и падение по OOM.