Sobes.tech
Senior

El servicio realiza solicitudes a una API externa que comenzó a responder en 10 segundos. Las goroutines se acumulan, la memoria crece, y el servicio se cae por OOM. ¿Cómo protegerse?

sobes.tech AI

Respuesta de la IA

Проблема в том, что горутины блокируются на долгих запросах к внешнему 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.