跪拜 Guibai
← All articles
Backend · Interview

Short Polling to WebSocket: Four Ways to Push Real-Time Data to a Dashboard

By 程序员代码随笔 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Most real-time dashboard advice jumps straight to WebSocket, but SSE handles the common unidirectional-push case with less code, automatic reconnection, and no protocol upgrade. The seven production pitfalls—especially Nginx buffering and Spring’s async timeout—are exactly what turn a working local demo into a silent failure after deploy.

Summary

Four push schemes are compared side by side: short polling, long polling, Server-Sent Events, and WebSocket. Each gets a working Spring Boot 3.2 controller and vanilla-JS frontend snippet, plus a breakdown of who holds the data initiative—client pull versus server push. The comparison table covers real-time ceiling, connection model, browser compatibility, and HTTP/2 behavior.

Seven production traps are called out explicitly: Nginx buffering silently breaking SSE streams, Spring MVC’s 30-second async timeout killing long-lived emitters, `scheduleAtFixedRate` causing concurrent writes to the same SseEmitter, WebSocket messages vanishing in multi-instance deployments, connection leaks across all three long-lived patterns, SSE’s inability to carry custom auth headers, and the gap between push channel and actual data source. Each trap includes the concrete fix.

A decision tree and one-line recommendations steer the reader toward SSE for most internal dashboards, WebSocket only when bidirectional messaging is required, and short polling for rapid prototypes. MQTT and RSocket are noted as advanced alternatives for IoT and reactive stacks respectively.

Takeaways
Short polling is a pull model: the client asks on a timer, and real-time ceiling equals the polling interval.
Long polling holds the HTTP request open on the server until new data arrives, then the client immediately re-requests.
SSE uses a single HTTP long connection with `text/event-stream`; the browser’s EventSource API handles reconnection automatically.
WebSocket upgrades HTTP to a full-duplex TCP connection with a lightweight frame protocol; STOMP adds pub/sub semantics on top.
SSE cannot carry custom headers, so JWT tokens must go in the URL or be exchanged for a short-lived ticket first.
Nginx’s default `proxy_buffering on` will batch SSE events and deliver them in one chunk unless explicitly disabled.
Spring MVC’s `spring.mvc.async.request-timeout` defaults to 30 seconds and will kill an SseEmitter even if you pass `0L`.
`scheduleAtFixedRate` can stack concurrent writes onto the same SseEmitter; `scheduleWithFixedDelay` avoids the race.
In a multi-instance WebSocket deployment, a simple in-memory broker delivers messages only to clients connected to the local instance.
Every long-lived connection pattern—long polling, SSE, WebSocket—can leak threads or file descriptors if teardown callbacks are not wired correctly.
Conclusions

SSE is underused in the Java ecosystem largely because Spring’s async timeout and Nginx’s default buffering combine to break it silently, making developers blame the protocol rather than the config.

The article’s framing around “who holds the data initiative” is a more useful mental model than raw latency numbers; it explains why long polling still exists alongside technically superior options.

STOMP over WebSocket adds message-broker semantics that make horizontal scaling easier, but the article correctly notes that most dashboard use cases don’t need bidirectional communication at all.

The seven production pitfalls form a de facto checklist that applies to nearly any server-push implementation, regardless of language or framework.

Concepts & terms
Short Polling
Client repeatedly sends HTTP requests on a fixed interval; the server responds immediately with the current data. Real-time delay equals the polling interval.
Long Polling (Comet)
Client sends an HTTP request; the server holds it open until new data is available or a timeout occurs, then responds. The client immediately issues a new request.
SSE (Server-Sent Events)
HTML5 standard where the server pushes data over a single HTTP long connection using `text/event-stream` content type. The browser’s EventSource API handles automatic reconnection.
WebSocket
Protocol that upgrades an HTTP connection to a full-duplex TCP connection via an Upgrade handshake, enabling bidirectional frame-based communication with minimal overhead.
STOMP
Simple Text Oriented Messaging Protocol—a sub-protocol over WebSocket that provides topic-based pub/sub semantics, making it easier to broadcast messages to subscribed clients.
DeferredResult
Spring MVC’s asynchronous return type that releases the servlet thread while waiting for a result to be set later, used for long polling without blocking the thread pool.
SseEmitter
Spring’s abstraction for SSE, returning a handle that can send events to the client over an open HTTP connection. Requires careful cleanup of scheduled tasks on completion, timeout, or error.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗