Ограничьте ожидание сетевым тайм-аутом и бюджетом попыток; для расчётов на часы используйте очередь и получение результата по идентификатору задачи. Обычная горутина вокруг зависшего вызова проблему не решает.
Надёжный доступ к медленному и нестабильному сервису
Ограничьте ожидание сетевым тайм-аутом и бюджетом попыток; для расчётов на часы используйте очередь и получение результата по идентификатору задачи. Обычная горутина вокруг зависшего вызова проблему не решает.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Существует внешний сервис, отвечающий за расчёт скидок для клиентов. Его реализация представляет собой старый монолит, который работает непредсказуемо: время ответа может колебаться от нескольких секунд до нескольких часов. Требуется спроектировать механизм, позволяющий ограничить влияние такой задержки и сделать взаимодействие с монолитом более предсказуемым и отказоустойчивым.
package main
import (
"fmt"
"http"
)
// Функция обращается к устаревшему монолиту и может работать очень медленно.
func fetchDiscount() float64 {
disc, _ := http.Get("http://discounts.com/my")
return disc
}
func main() {
fmt.Printf("Ваша скидка: %v", fetchDiscount())
}
Ответ
Ограничьте ожидание сетевым тайм-аутом и бюджетом попыток; для расчётов на часы используйте очередь и получение результата по идентификатору задачи. Обычная горутина вокруг зависшего вызова проблему не решает.
Исходник не компилируется: пакет — net/http, а Get возвращает *http.Response и error, не скидку. Нужны проверка статуса, ограничение размера, разбор тела и его закрытие. Передавайте context в HTTP-запрос и ограничивайте конкурентность. Circuit breaker защищает при серии сбоев; кэш или безопасный fallback согласуйте с бизнесом. Повторы — только допустимые, с backoff и идемпотентностью. Отмена клиента не гарантирует остановку вычисления в старом монолите.