middle
Как реализовать Server-Sent Events (SSE) с помощью WebFlux?
Server-Sent Events (SSE) — стандарт HTML5 для однонаправленной потоковой передачи данных от сервера к клиенту через HTTP. В отличие от WebSocket, SSE работает поверх обычного HTTP и поддерживает автоматическое переподключение браузером.
Простейший SSE-эндпоинт
Пример
@RestController
public class SseController {
@GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(i -> "Event #" + i);
}
}
SSE с типизированными событиями
Пример
@GetMapping(value = "/notifications", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<NotificationDto>> streamNotifications() {
return notificationService.getNotifications()
.map(notification -> ServerSentEvent.<NotificationDto>builder()
.id(notification.getId().toString())
.event(notification.getType())
.data(notification)
.retry(Duration.ofSeconds(5))
.build());
}
Реальный пример — лента обновлений с Sinks + SSE
@Service
public class UpdateService {
private final Sinks.Many<Update> sink =
Sinks.many().multicast().onBackpressureBuffer(100);
public void publishUpdate(Update update) {
sink.tryEmitNext(update);
}
public Flux<Update> getUpdates() {
return sink.asFlux();
}
}
@RestController
public class UpdateController {
private final UpdateService updateService;
@GetMapping(value = "/updates/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<Update>> stream() {
return updateService.getUpdates()
.map(update -> ServerSentEvent.builder(update)
.id(UUID.randomUUID().toString())
.event("update")
.build());
}
}
Клиент на JavaScript
Пример
const eventSource = new EventSource('/updates/stream');
eventSource.addEventListener('update', (event) => {
const data = JSON.parse(event.data);
console.log('Получено обновление:', data);
});
eventSource.onerror = (error) => {
console.error('SSE ошибка:', error);
// Браузер автоматически переподключится
};
Частые ошибки
- Не указать
produces = TEXT_EVENT_STREAM_VALUE— клиент получит JSON-массив вместо потока - Отправлять слишком большие объекты — SSE предназначен для лёгких уведомлений
- Забывать про CORS — SSE-запросы подчиняются политике CORS
Как используется в 2026
- SSE — стандартный подход для push-уведомлений, дашбордов, live-лент
- Для двунаправленного обмена — WebSocket, для однонаправленного — SSE
- SSE хорошо работает с CDN и прокси (в отличие от WebSocket, требующего Upgrade)
- В микросервисной архитектуре SSE используется совместно с Kafka
На собеседовании: покажите знание практической реализации: MediaType.TEXT_EVENT_STREAM_VALUE + Flux. Частая ошибка — путать SSE с WebSocket. SSE — однонаправленный (сервер -> клиент), работает поверх HTTP, браузер переподключается автоматически. WebSocket — двунаправленный, требует Upgrade.