@@ -37665,7 +37665,7 @@ sections <<websocket-stomp-handle-broker-relay-configure>> and
37665
37665
<<websocket-stomp-handle-user>> for more information on authentication.
37666
37666
37667
37667
37668
- [[websocket-stomp-handle ]]
37668
+ [[websocket-stomp-message-flow ]]
37669
37669
==== Flow of Messages
37670
37670
37671
37671
When a STOMP endpoint is configured, the Spring application becomes the broker to
@@ -38047,6 +38047,169 @@ for purging inactive destinations.
38047
38047
38048
38048
38049
38049
38050
+
38051
+ [[websocket-stomp-configuration-performance]]
38052
+ ==== Configuration and Performance
38053
+
38054
+ There is no silver bullet when it comes to performance. Many factors may
38055
+ affect it including the size of messages, the volume, whether application
38056
+ methods perform work that requires blocking, as well as external factors
38057
+ such as network speed and others. The goal of this section is to provide
38058
+ an overview of the available configuration options along with some thoughts
38059
+ on how to reason about scaling.
38060
+
38061
+ In a messaging application messages are passed through channels for asynchronous
38062
+ executions backed by thread pools. Configuring such an application requires
38063
+ good knowledge of the channels and the flow of messages. Therefore it is
38064
+ recommended to review <<websocket-stomp-message-flow>>.
38065
+
38066
+ The obvious place to start is to configure the thread pools backing the
38067
+ `"clientInboundChannel"` and the `"clientOutboundChannel"`. By default both
38068
+ are configured at twice the number of available processors.
38069
+
38070
+ If the handling of messages in annotated methods is mainly CPU bound then the
38071
+ number of threads for the `"clientInboundChannel"` should remain close to the
38072
+ number of processors. If the work they do is more IO bound and requires blocking
38073
+ or waiting on a database or other external system then the thread pool size
38074
+ will need to be increased.
38075
+
38076
+ [NOTE]
38077
+ ====
38078
+ `ThreadPoolExecutor` has 3 important properties. Those are the core and
38079
+ the max thread pool size as well as the capacity for the queue to store
38080
+ tasks for which there are no available threads.
38081
+
38082
+ A common point of confusion is that configuring the core pool size (e.g. 10)
38083
+ and max pool size (e.g. 20) results in a thread pool with 10 to 20 threads.
38084
+ In fact if the capacity is left at its default value of Integer.MAX_VALUE
38085
+ then the thread pool will never increase beyond the core pool size since
38086
+ all additional tasks will be queued.
38087
+
38088
+ Please review the Javadoc of `ThreadPoolExecutor` to learn how these
38089
+ properties work and understand the various queuing strategies.
38090
+ ====
38091
+
38092
+ On the `"clientOutboundChannel"` side it is all about sending messages to WebSocket
38093
+ clients. If clients are on a fast network then the number of threads should
38094
+ remain close to the number of available processors. If they are slow or on
38095
+ low bandwith they will take longer to consume messages and put a burden on the
38096
+ thread pool. Therefore increasing the thread pool size will be necessary.
38097
+
38098
+ While the workload for the "clientInboundChannel" is possible to predict --
38099
+ after all it is based on what the application does -- how to configure the
38100
+ "clientOutboundChannel" is harder as it is based on factors beyond
38101
+ the control of the application. For this reason there are two additional
38102
+ properties related to the sending of messages. Those are the `"sendTimeLimit"`
38103
+ and the `"sendBufferSizeLimit"`. Those are used to configure how long a
38104
+ send is allowed to take and how much data can be buffered when sending
38105
+ messages to a client.
38106
+
38107
+ The general idea is that at any given time only a single thread may be used
38108
+ to send to a client. All additional messages meanwhile get buffered and you
38109
+ can use these properties to decide how long sending a message is allowed to
38110
+ take and how much data can be buffered in the mean time. Please review the
38111
+ Javadoc of XML schema for this configuration for important additional details.
38112
+
38113
+ Here is example configuration:
38114
+
38115
+ [source,java,indent=0]
38116
+ [subs="verbatim,quotes"]
38117
+ ----
38118
+ @Configuration
38119
+ @EnableWebSocketMessageBroker
38120
+ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
38121
+
38122
+ @Override
38123
+ public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
38124
+ registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024);
38125
+ }
38126
+
38127
+ // ...
38128
+
38129
+ }
38130
+ ----
38131
+
38132
+ [source,xml,indent=0]
38133
+ [subs="verbatim,quotes,attributes"]
38134
+ ----
38135
+ <beans xmlns="http://www.springframework.org/schema/beans"
38136
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
38137
+ xmlns:websocket="http://www.springframework.org/schema/websocket"
38138
+ xsi:schemaLocation="
38139
+ http://www.springframework.org/schema/beans
38140
+ http://www.springframework.org/schema/beans/spring-beans.xsd
38141
+ http://www.springframework.org/schema/websocket
38142
+ http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
38143
+
38144
+ <websocket:message-broker>
38145
+ <websocket:transport send-timeout="15000" send-buffer-size="524288" />
38146
+ <!-- ... -->
38147
+ </websocket:message-broker>
38148
+
38149
+ </beans>
38150
+ ----
38151
+
38152
+ The WebSocket transport configuration shown above can also be used to configure the
38153
+ maximum allowed size for incoming STOMP messages. Although in theory a WebSocket
38154
+ message can be almost unlimited in size, in pracitce WebSocket servers impose
38155
+ limits. For example 8K on Tomcat and 64K on Jetty. For this reason STOMP clients
38156
+ such as stomp.js split larger STOMP messages at 16K boundaries and send them as
38157
+ multiple WebSocket messages thus requiring the server to buffer and re-assemble.
38158
+
38159
+ Spring's STOMP over WebSocket support does this so applications can configure the
38160
+ maximum size for STOMP messages irrespective of WebSocket server specific message
38161
+ sizes. Do keep in mind that the WebSocket message size will be automatically
38162
+ adjusted if necessary to ensure they can carry 16K WebSocket messages at a
38163
+ minimum.
38164
+
38165
+ Here is example configuration:
38166
+
38167
+ [source,java,indent=0]
38168
+ [subs="verbatim,quotes"]
38169
+ ----
38170
+ @Configuration
38171
+ @EnableWebSocketMessageBroker
38172
+ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
38173
+
38174
+ @Override
38175
+ public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
38176
+ registration.setMessageSizeLimit(128 * 1024);
38177
+ }
38178
+
38179
+ // ...
38180
+
38181
+ }
38182
+ ----
38183
+
38184
+ [source,xml,indent=0]
38185
+ [subs="verbatim,quotes,attributes"]
38186
+ ----
38187
+ <beans xmlns="http://www.springframework.org/schema/beans"
38188
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
38189
+ xmlns:websocket="http://www.springframework.org/schema/websocket"
38190
+ xsi:schemaLocation="
38191
+ http://www.springframework.org/schema/beans
38192
+ http://www.springframework.org/schema/beans/spring-beans.xsd
38193
+ http://www.springframework.org/schema/websocket
38194
+ http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
38195
+
38196
+ <websocket:message-broker>
38197
+ <websocket:transport message-size="131072" />
38198
+ <!-- ... -->
38199
+ </websocket:message-broker>
38200
+
38201
+ </beans>
38202
+ ----
38203
+
38204
+ An important point about scaling is using multiple application instances.
38205
+ Currently this is not possible to do that with the simple broker.
38206
+ However when using a full-featured broker such as RabbitMQ, each application
38207
+ instance connects to the broker and messages broadcast from one application
38208
+ instance are broadcast to WebSocket clients connected through all
38209
+ application instances.
38210
+
38211
+
38212
+
38050
38213
[[websocket-stomp-testing]]
38051
38214
==== Testing Annotated Controller Methods
38052
38215
0 commit comments