Ответ
Да, я знаком с Server-Sent Events (SSE). Это технология, которая позволяет серверу отправлять обновления клиенту в одностороннем порядке через одно HTTP-соединение. В отличие от WebSockets, SSE проще и работает поверх стандартного HTTP, но не поддерживает двунаправленную связь.
Ключевые особенности SSE:
- Однонаправленная связь: Только сервер может отправлять данные клиенту (server -> client).
- Простота: Легко реализуется как на сервере, так и на клиенте (стандартный
EventSource
API в браузерах). - Автоматическое переподключение: Браузерный клиент автоматически пытается восстановить соединение в случае обрыва.
Сценарии применения:
SSE идеально подходит для задач, где не требуется ответ от клиента, например:
- Лента новостей или обновлений в реальном времени.
- Системы уведомлений.
- Отображение статуса выполнения долгой задачи (например, обработка видео).
- Live-дэшборды с котировками или метриками.
Пример реализации на Go
Сервер должен установить специальные заголовки и отправлять события в формате data: <сообщение>nn
.
func sseHandler(w http.ResponseWriter, r *http.Request) {
// Устанавливаем необходимые заголовки для SSE
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// http.Flusher необходим для отправки данных клиенту по частям,
// а не после завершения всего ответа.
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
return
}
// Бесконечный цикл для отправки событий
for {
select {
// Если клиент закрыл соединение, r.Context().Done() получит сигнал
case <-r.Context().Done():
fmt.Println("Client disconnected")
return
// Отправляем событие каждую секунду
default:
// Формат события: "data: {message}nn"
fmt.Fprintf(w, "data: Текущее время: %snn", time.Now().Format(time.RFC1123))
flusher.Flush() // Отправляем буферизированные данные клиенту
time.Sleep(1 * time.Second)
}
}
}
Клиентская часть (JavaScript)
// Создаем подключение к нашему SSE-эндпоинту
const eventSource = new EventSource('/sse');
// Обработчик для всех сообщений без указанного event
eventSource.onmessage = (event) => {
console.log('Новое сообщение:', event.data);
};
// Обработчик ошибок
eventSource.onerror = (err) => {
console.error("EventSource failed:", err);
};