Sobes.tech
Назад к вопросам
Senior
4

Сервис делает запросы во внешнее API, которое начало отвечать по 10 секунд. Горутины копятся, память растёт, сервис падает по OOM. Как защитить?

Компании, где спрашивали
А7

Ответ от нейросети

sobes.tech AI

Проблема в том, что горутины блокируются на долгих запросах к внешнему API, что приводит к накоплению горутин и росту потребления памяти.

Как защитить сервис:

  1. Ограничить количество одновременно выполняющихся запросов — использовать семафор или пул воркеров, чтобы не создавать слишком много горутин.

  2. Установить таймауты на HTTP-запросы — использовать контекст с таймаутом (context.WithTimeout) или настроить таймауты в HTTP-клиенте, чтобы запросы не висели бесконечно.

  3. Обрабатывать ошибки и отменять запросы при таймауте — чтобы горутины не блокировались.

  4. Использовать контекст для отмены запросов — передавать 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.