The labs on this site need JavaScript to run. The same content is written out below.
Learn › Networking › HTTP
Polling, SSE, and WebSocket
Four ways to tell the browser what happened on the server
HTTP works by the client asking and the server answering, so even when the server has a new notification, it cannot speak first. The options are to ask periodically (polling), to hold the answer back (long polling), to keep the connection open and stream data through it (SSE), or to switch to a two-way channel (WebSocket).
Checked against documentation and standards · Checked against the HTML standard, the WebSocket standard (RFC 6455), and the Spring documentation
Concepts in this lab
- SSE (server-sent events) and polling
- Polling is an approach in which the client repeatedly asks the server, at regular intervals, whether there is new data. SSE keeps one HTTP connection open while the server keeps sending events to the client, and data can travel in one direction only, from the server to the client. For cases such as notifications, where only the server needs to send, it is simpler than WebSocket.
- WebSocket
- A communication protocol that lets a client and a server keep one connection open and send messages freely from either side. In HTTP, the server can respond only after the client sends a request. With this protocol, the server can send data first, so it is used for chat and real-time notifications.
- HTTP as a stateless protocol
- HTTP is a communication protocol in which a client sends a request and a server responds. Stateless means that the server does not remember the content of earlier requests, so each request must carry all the information needed to process it. Because the server keeps no state, any server can take a request, which makes it easy to add servers. Information that must carry over, such as a login state, is kept with cookies, sessions, or tokens.
Try these
- Default settings — Polling every 5s. Half of the 6 requests end with "no news".
- Polling interval of 1s — The delay gets shorter, but the requests grow to 30.
- Long polling — The server responds the moment news arrives. The number of requests is close to the number of notifications.
- SSE — With one connection, the server sends as things happen.
- When you need two-way communication — If the client also sends often, as in a chat, WebSocket is the right fit.
- SSE, but the client also sends often — Each message the client sends becomes a separate HTTP request.
Running with the default settings
- Every 5 seconds, the browser requests "Are there any new notifications?" The server returns the notifications that have piled up until then, or an empty response if there are none.
- 5s: The browser sent a request. It received the 1 notification created in the meantime. They were created at 3.7s, but had to wait until the next request.
- 10s: The browser sent a request. There were no new notifications, so it received an empty response.
- 15s: The browser sent a request. It received the 1 notification created in the meantime. They were created at 13.7s, but had to wait until the next request.
- 20s: The browser sent a request. There were no new notifications, so it received an empty response.
- 25s: The browser sent a request. It received the 1 notification created in the meantime. They were created at 23.7s, but had to wait until the next request.
- 30s: The browser sent a request. There were no new notifications, so it received an empty response.
- Of the 6 requests in 30 seconds, 3 ended empty-handed.
Result of this run
- Polling is the simplest to implement. But if the interval is long, notifications arrive late, and if it is short, requests that gain nothing pile up on the server. With many users, those requests alone become a load.
Code
// Browser
setInterval(async () => {
const res = await fetch("/notifications?after=" + lastId);
show(await res.json()); // an empty array if there is nothing
}, 5000);
Assumptions of this model
Notifications are assumed to be created evenly across the 30-second window. Network round-trip time is ignored in the delivery delay. The messages the client sends are fixed at 10 per 30 seconds. The long-polling time limit is set to 30 seconds. The behavior of the four methods follows the explanations in the HTML standard (EventSource), the WebSocket standard (RFC 6455), and the Spring documentation.
Previous lab: CORS · Next lab: TLS handshake