From d30cb17c91e4e5eeda29e9c1836f734145ecc9b1 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Sun, 23 Mar 2014 22:49:33 -0400 Subject: [PATCH] Polish SockJS documentation --- src/asciidoc/index.adoc | 98 ++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 54 deletions(-) diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc index e49c4a9566..923990103c 100644 --- a/src/asciidoc/index.adoc +++ b/src/asciidoc/index.adoc @@ -37260,73 +37260,63 @@ configuration options, for example, to specify which transports to include. +[[websocket-fallback-sockjs-servlet3-async]] +==== SockJS and Servlet 3 Async Support + +HTTP streaming and HTTP long polling SockJS transports require a connection to remain +open longer than usual. For an overview of these techniques see +https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post]. + +In Servlet containers this is done through Servlet 3 async support that +allows exiting the Servlet container thread processing a request and continuing +to write to the response from another thread. + +A specific issue is the Servlet API does not provide notifications for a client +that has gone away, see https://java.net/jira/browse/SERVLET_SPEC-44[SERVLET_SPEC-44]. +However, Servlet containers raise an exception on subseqeunt attempts to write +to the response. Since Spring's SockJS Service support sever-sent heartbeats (every +25 seconds by default), that means a client disconnect is usually detected within that +time period or earlier if a message are sent more frequently. + +[NOTE] +==== +As a result network IO failures may occur simply because a client has disconnected, which +can fill the log with unnecessary stack traces. Spring makes a best effort to identify +such network failures that represent client disconnects (specific to each server) and log +a more minimal message using the dedicated log category `DISCONNECTED_CLIENT_LOG_CATEGORY` +defined in `AbstractSockJsSession`. If you need to see the stack traces, set that +log category to TRACE. +==== + [[websocket-fallback-sockjs-explained]] ==== How SockJS Works -An in-depth description of how SockJS works is beyond the scope of this document. -This section summarizes a few key facts to aid with understanding. -The SockJS protocol itself is defined in a +This is a question beyond the scope of this document. The SockJS protocol +is defined in the form of a Python https://github.com/sockjs/sockjs-protocol/blob/master/sockjs-protocol-0.3.3.py[test suite], -with comments explaining the protocol. There is also an -http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[HTML version of that test] -showing comments on the right and code on the left. +with narrative in comments. There is an +http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[HTML formatted version] +of the test showing narrative on the right and client code on the left. -The SockJS client issues HTTP requests with this URL structure: +The SockJS client begins with an initial `"/info"` request to obtain basic +information from the server. Then the client selects a transport and sends +a series of session requests: -.SockJS URL ---- -http://host:port/{path-to-sockjs-endpoint}/{server-id}/{session-id}/{transport} +http://host:port/{sockjs-endpoint}/{server-id}/{session-id}/{transport} ---- -The WebSocket transport type uses a single HTTP connection to perform a -WebSocket handshake and establish an actual WebSocket session. HTTP-based -transports on the other hand must simulate the WebSocket API and at any time -may use two HTTP connections -- one for server-to-client messages, via -https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates[HTTP streaming or long polling], -and another for sending client messages to the server via HTTP POST. - -The session id is useful with HTTP transports to associate individual HTTP -requests that belong to the same SockJS session. The server id is not used in the -protocol but is added to help in clustered environments. +The WebSocket transport type only needs a single HTTP connection for the handshake. +HTTP-based transports use one connection for sending messages from server to client +and separate requests for sending messages from client to server. +The session id is used to correlate HTTP requests belonging to the same SockJS +session. The server id is not used in the protocol but is added to help in +clustered environments. -SockJS adds a minimal amount of message framing. For example, the server can send +The SockJS protocol requires minimal message framing. The server for examples sends an "open frame" (the letter +o+), a "heartbeat frame" (the letter +h+), or a "close frame" (the letter +c+); while the client sends messages as a JSON-encoded array prepended with the letter `a` (e.g. +a["message1","message2"]+). -By default the server sends a heartbeat frame every 25 seconds to keep proxies -and loadbalancers from timing out the connection. - - - -[[websocket-fallback-sockjs-spring]] -==== Spring's SockJS Support -In the Spring Framework, server-side support for the SockJS protocol is provided through a -hierarchy of classes that implement the `SockJsService` interface, while -`SockJsHttpRequestHandler` integrates the service into HTTP request processing. - -To implement HTTP streaming and long polling in Servlet containers (both of which require -an HTTP connection to remain open longer than usual), Spring's SockJS support -relies on Servlet 3 async support. - -[WARNING] -==== -The Servlet API does not provide notifications when a client disconnects, -see https://java.net/jira/browse/SERVLET_SPEC-44[SERVLET_SPEC-44]. However, -Serlvet containers typically raise an IOException on the next attempt to write -to the response at which point the SockJS session is closed. Since the -SockJsService sends a heartbeat every 25 seconds, typically a disconnected -client should be detected within that time period. - -This also means that network IO failures may occur simply because a client has gone -away and that can fill the logs with unnecessary stack traces. -We make a best effort to identify such network failures, on a per-server basis, and log -them under a separate log category, see `AbstractSockJsSession#DISCONNECTED_CLIENT_LOG_CATEGORY`. -A simple one-line message is logged at DEBUG level using this category while a full -stack trace is shown at TRACE level. -==== - - - [[websocket-stomp]] === STOMP Messaging