HTTP


HTTP 1.0

  • Open TCP connection
  • Send GET Request
  • Receive Response
  • Close TCP connection

TCP 3-way handshake expensive

HTTP 1.1

  • Open TCP connection
  • Send GET Request
  • Receive Response
  • Close TCP connection if I want to

WebSockets


  • Open connection
  • GET 1.1 UPGRADE
  • 101 - Switching Protocols
  • No longer HTTP
  • Bidirectional no order

Server Sent Events


  • Open connection
  • Send GET text/event-stream
  • Respond : Content-Type = text/event-stream / Transfer-Encoding chunked
  • keep sending more chunks
  • Server or Client can close connection

SSE Example


SSE use cases

  • Live Feed
  • Showing client progress
  • Logging

Coding

res.setHeader("Content-Type", "text/event-stream")
res.write("data: " + "hello!\n\n")

SSE Pros and Cons


Pros

  • Lightweight
    • packets are small because there are no headers unlike the websocket
  • HTTP & HTTP/2 compatible
  • Firewall friendly (standard)

Cons

  • Proxying is tricky
  • L7 L/B challenging (timeouts)
    • client cannot keep connection alive
  • Stateful, difficult to horizontally scale

Do I have to use SSE?

  • WebSockets
    • sse is limited only purely server sent events
    • overhead to HTTP there are its own protocol headers
  • Long polling

실시간 기술


Polling

  • 특정 주기로 요청을 보낸다.
  • 서버에 변화가 없어도 계속해서 요청을 보내기 때문에 불필요한 통신이 많이 이루어진다.
  • 기존 우리 서버는 0.5초 간격으로 서버에게 요청을 보내고 있었다.

Long Polling

  • 서버에서 접속을 열어두고 이벤트 발생 시 응답을 보낸다.
  • 이벤트가 발생하면 즉시 응답이 이루어져 실시간 성능이 뛰어나다.
  • 클라이언트가 많은 경우 이벤트 발생 시 동시에 Response 를 보내고 Request 를 받기 때문에 순간적으로 큐에 많은 양의 명령이 쌓여 서버에 무리가 간다.

Web Socket

  • 서버와 클라이언트가 TCP connection 을 유지하여 실시간으로 데이터를 주고받는 양방향 통신이다.

Server Sent Event

  • 서버와 클라이언트가 TCP connection 을 유지하여 서버 → 클라이언트 방향으로만 통신하는 단방향 통신이다.
  • Web Socket 은 금지 기술이었고 SSE 로도 충분히 원하는 결과를 얻어낼 수 있을 것이라 판단하여 SSE 를 사용했다.

Spring SseEmitter


Polling

NginX 설정

server {
    ...

    location / {
        ...

        # SSE through NginX
        proxy_set_header Connection '';
        proxy_http_version 1.1;
        chunked_transfer_encoding off;
        proxy_buffering off;
        proxy_cache off;

        ...
    }

    ...
}

현재 프로젝트 구조에선 NginX 를 통해 백엔드 서버와 통신하고 있다.

SSE 를 NginX 를 통해 클라이언트에게 보내주기 위해선 location 내부에 위와 같은 설정이 추가되어야 한다.

References