Mayderson Mello
Posted on April 8, 2023
Server-Sent Events (SSE) é uma tecnologia que permite a comunicação unidirecional entre o servidor e o cliente em tempo real. SSE é uma alternativa aos WebSockets que oferece várias vantagens, como menor sobrecarga de rede e menor uso de recursos. Neste tutorial, iremos aprender como implementar SSE em Go e compará-lo com WebSockets.
O que é SSE?
SSE é um protocolo de comunicação baseado em HTTP que permite que o servidor envie eventos para o cliente. O cliente se inscreve em um fluxo SSE, que é uma conexão persistente entre o cliente e o servidor. O servidor envia eventos em formato de texto para o cliente, que é capaz de processá-los em tempo real. Os eventos podem ser nomeados e o payload pode ser em formato de texto ou JSON.
Como implementar?
O exemplo a seguir mostra como implementar SSE utilizando Golang, mas não se apegue a linguagem pois pode ser qualquer outra, basta definir os Headers corretos que você será capaz reproduzir.
Back-end (Golang)
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
http.HandleFunc("/sse", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
messageCounter := 0
for {
someMessage := fmt.Sprintf("Message: %v", messageCounter)
eventName := "event: myCustomEvent\n"
payloadMessage := fmt.Sprintf("data: %s\n\n", someMessage)
w.Write([]byte(eventName))
w.Write([]byte(payloadMessage))
time.Sleep(1 * time.Second)
w.(http.Flusher).Flush()
messageCounter++
}
})
http.ListenAndServe(":3333", nil)
}
A rota /sse
define os cabeçalhos necessários para enviar eventos SSE. O cabeçalho Content-Type
é definido como text/event-stream
, Cache-Control
é definido como no-cache
para evitar o armazenamento em cache e Connection
é definido como keep-alive
para manter a conexão aberta. Em seguida, o servidor inicia um loop infinito para enviar eventos SSE. O evento é opcional e pode ser usado para especificar o tipo de evento que está sendo enviado. O payload contém os dados que estão sendo enviados.
O uso do
\n
é obrigatório, você pode observar que uso ele ao definir o nome do evento e payload da mensagem. O SSE vai conseguir interpretar quando essas informações foram definidas após essa quebra de linha, por fim, o\n
adicional informa que acabou aquele evento.
Exemplo de como vai ficar no final após a interpretação:
event: myCustomEvent
data: Message: 1
event: myCustomEvent
data: Message: 2
Front-end (HTML + JavaScript)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSE</title>
</head>
<body>
<h1>SSE - Real Time Messages</h1>
<ul id="messages"></ul>
<script>
const eventSource = new EventSource('/sse');
eventSource.addEventListener('myCustomEvent', event => {
const messagesElement = document.getElementById('messages');
const li = document.createElement('li');
li.innerText = event.data;
messagesElement.appendChild(li);
console.log(event);
});
</script>
</body>
</html>
O código acima é muito simples, basicamente vamos estar recebendo as mensagens que o nosso Back-end vai mandar, e vamos adicionar elas em tela, somente isso.
A instância do EventSource
, recebe a URL do endpoint SSE que o servidor está ouvindo (/sse neste caso). Isso estabelece uma conexão persistente entre o cliente e o servidor, permitindo que o servidor envie atualizações em tempo real para o cliente.
Em seguida, é adicionado um ouvinte de eventos para o evento personalizado myCustomEvent
, que é enviado pelo servidor. Quando esse evento é recebido, uma nova linha de lista li
é criada, contendo o texto da mensagem que foi enviada pelo servidor. A linha de lista é então adicionada ao elemento ul
com o id messages
, que é onde as mensagens são exibidas na página.
Vantagens e Desvantagens do SSE
SSE tem várias vantagens em relação aos WebSockets. A primeira é que ele é baseado em HTTP e usa a porta HTTP padrão (80), o que significa que ele pode passar por firewalls e proxies sem problemas. Além disso, o SSE requer menos sobrecarga de rede e recursos do servidor do que o WebSocket, porque apenas o servidor pode enviar dados. Isso significa que o servidor não precisa lidar com tantas conexões de saída e, portanto, pode lidar com mais conexões de entrada. Finalmente, o SSE é fácil de implementar, pois é baseado em HTTP e usa o mesmo modelo de programação.
No entanto, o SSE também tem algumas desvantagens. A primeira é que ele só suporta comunicação unidirecional (do servidor para o cliente), o que significa que o cliente não pode enviar dados para o servidor. Além disso, o SSE não é suportado por todos os navegadores e plataformas, o que significa que você precisará testar se o SSE funciona em todos os navegadores e plataformas que você deseja suportar.
Comparação SSE vs WebSockets
Embora SSE e WebSockets possam parecer semelhantes, eles têm algumas diferenças importantes. A principal diferença é que o WebSocket é bidirecional, o que significa que tanto o cliente quanto o servidor podem enviar dados. Isso torna o WebSocket mais adequado para aplicativos em tempo real que exigem interação bidirecional entre o cliente e o servidor, como jogos online ou aplicativos de bate-papo. O SSE, por outro lado, é mais adequado para aplicativos unidirecionais, como feeds de notícias ou atualizações de preços.
Além disso, o WebSocket usa um protocolo de comunicação personalizado que é implementado em um nível mais baixo do que o HTTP. Isso significa que o WebSocket é capaz de suportar recursos avançados, como multiplexação de canais, compressão de dados e autenticação do lado do servidor. O SSE, por outro lado, é implementado como um recurso do HTTP e, portanto, não pode usar esses recursos avançados.
Posted on April 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.