← Назад к вопросам
Что будешь делать с запросами, которые не успевает обработать сервис
2.0 Middle🔥 111 комментариев
#REST API и микросервисы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Стратегии обработки перегруженных запросов в сервисе
Это один из классических вопросов про производительность и надёжность. Когда сервис не успевает обрабатывать запросы, нужна многоуровневая стратегия.
1. Очередь сообщений (асинхронная обработка)
Основной подход — перенести тяжёлую работу в фоновую задачу:
// REST Controller
@RestController
requestMapping("/api/orders")
public class OrderController {
@Autowired
private KafkaTemplate<String, OrderEvent> kafkaTemplate;
@PostMapping
public ResponseEntity<Map<String, String>> createOrder(@RequestBody Order order) {
// Быстро сохраняем в БД и отправляем событие в Kafka
Order saved = orderRepository.save(order);
kafkaTemplate.send("orders.created", new OrderEvent(saved.getId()));
return ResponseEntity.accepted()
.body(Map.of("id", saved.getId(), "status", "RECEIVED"));
}
}
// Consumer обрабатывает асинхронно
@Service
public class OrderProcessor {
@KafkaListener(topics = "orders.created")
public void processOrder(OrderEvent event) {
Order order = orderRepository.findById(event.getId()).orElse(null);
// Тяжёлая обработка (отправка писем, расчёты и т.д.)
processHeavyWork(order);
}
}
2. Кэширование ответов
Избежать повторной обработки:
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUser(String id) {
// Вызовется только один раз за TTL
return database.findUser(id);
}
@CacheEvict(value = "users", key = "#id")
public void updateUser(String id, User user) {
database.updateUser(id, user);
}
}
3. Rate Limiting и Throttling
Ограничить количество одновременных запросов:
@Component
public class RateLimitingFilter extends OncePerRequestFilter {
private RateLimiter rateLimiter = RateLimiter.create(100); // 100 запросов/сек
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
if (!rateLimiter.tryAcquire()) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().write("Rate limit exceeded");
return;
}
filterChain.doFilter(request, response);
}
}
4. Load Balancing и горизонтальное масштабирование
Распределить нагрузку на несколько инстансов:
- Nginx/HAProxy перед несколькими инстансами сервиса
- Spring Cloud Load Balancer для микросервисов
- Автоскейлинг в Kubernetes
5. Circuit Breaker паттерн
Не отправлять запросы перегруженному сервису:
@Service
public class PaymentService {
@CircuitBreaker(name = "paymentService", fallbackMethod = "paymentFallback")
public String processPayment(String orderId) {
// Если сервис перегружен, Resilience4j вернёт fallback
return externalPaymentService.charge(orderId);
}
public String paymentFallback(String orderId, Exception e) {
// Отложенная обработка или сообщение об ошибке
logger.warn("Payment service unavailable, queuing order: " + orderId);
return "Payment queued";
}
}
6. Timeout и Retry
Не дождаться вечно ответ:
@Retry(name = "paymentRetry", fallbackMethod = "retryFallback")
@Timeout(name = "paymentTimeout")
public void processWithRetry() {
externalService.call();
}
// application.yml
resilience4j:
retry:
instances:
paymentRetry:
maxAttempts: 3
waitDuration: 1000
timeout:
instances:
paymentTimeout:
timeoutDuration: 5s
7. Приоритизация запросов
Обрабатывать критичные запросы в первую очередь:
@Service
public class PriorityQueueService {
private PriorityQueue<Task> taskQueue = new PriorityQueue<>(
(t1, t2) -> Integer.compare(t2.getPriority(), t1.getPriority())
);
public void submitTask(Task task) {
taskQueue.offer(task);
}
public Task getNextTask() {
return taskQueue.poll(); // Вернёт задачу с наивысшим приоритетом
}
}
8. Graceful Degradation
Снизить качество обслуживания, но не упать совсем:
@Service
public class SearchService {
public List<Product> search(String query) {
try {
// Полная обработка с фильтрами
return elasticsearchService.advancedSearch(query);
} catch (TimeoutException e) {
// Fallback — простой поиск по БД
logger.warn("Elasticsearch timeout, using DB");
return databaseService.simpleSearch(query);
}
}
}
Комплексный подход
Лучшая стратегия — комбинация методов:
- Быстрый ответ → асинхронная обработка + очередь
- Контроль нагрузки → rate limiting + circuit breaker
- Масштабирование → горизонтальное (больше сервисов)
- Оптимизация → кэширование, индексы, правильные алгоритмы
- Graceful Degradation → деградация качества, а не crash
Выбор конкретной стратегии зависит от типа задачи (real-time, batch, streaming), SLA и архитектуры.