性能
性能方面没有万灵药。许多因素影响性能,包括消息的大小和数量、应用方法是否执行需要阻塞的工作,以及外部因素(如网络速度和其他问题)。本节旨在概述可用的配置选项,并提供关于如何考虑扩展的一些想法。
在消息应用中,消息通过通道传递以进行异步执行,这些通道由线程池支持。配置这样的应用需要很好地了解通道和消息流。因此,建议查阅消息流。
显而易见的起点是配置支持 clientInboundChannel
和 clientOutboundChannel
的线程池。默认情况下,两者都配置为可用处理器数量的两倍。
如果在注解方法中处理消息主要是 CPU 密集型工作,则 clientInboundChannel
的线程数应保持接近处理器数量。如果它们执行的工作更多是 IO 密集型,需要阻塞或等待数据库或其他外部系统,则线程池大小可能需要增加。
一个常见的困惑点是,配置核心池大小(例如 10)和最大池大小(例如 20)会导致一个拥有 10 到 20 个线程的线程池。实际上,如果容量保留其默认值 Integer.MAX_VALUE,则线程池永远不会超过核心池大小,因为所有附加任务都将被排队。 查看 |
在 clientOutboundChannel
侧,主要是向 WebSocket 客户端发送消息。如果客户端处于快速网络中,线程数应保持接近可用处理器数量。如果它们速度较慢或带宽较低,则需要更长时间来消费消息,并给线程池带来负担。因此,增加线程池大小变得必要。
虽然 clientInboundChannel
的工作负载是可以预测的——毕竟它基于应用做什么——但如何配置 "clientOutboundChannel" 更难,因为它基于应用无法控制的因素。因此,有两个附加属性与消息发送相关:sendTimeLimit
和 sendBufferSizeLimit
。您可以使用这些方法配置发送操作允许花费多长时间以及向客户端发送消息时可以缓冲多少数据。
一般想法是,在任何给定时间,只能使用单个线程向客户端发送消息。同时,所有附加消息都会被缓冲,您可以使用这些属性来决定发送消息允许花费多长时间以及在此期间可以缓冲多少数据。查看 XML schema 的 javadoc 和文档,了解重要的附加细节。
以下示例显示了可能的配置
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024);
}
// ...
}
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun configureWebSocketTransport(registration: WebSocketTransportRegistration) {
registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024)
}
// ...
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
https://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker>
<websocket:transport send-timeout="15000" send-buffer-size="524288" />
<!-- ... -->
</websocket:message-broker>
</beans>
您还可以使用前面显示的 WebSocket 传输配置来配置传入 STOMP 消息的最大允许大小。理论上,WebSocket 消息的大小几乎没有限制。实际上,WebSocket 服务器会施加限制——例如,Tomcat 上是 8K,Jetty 上是 64K。因此,像 stomp-js/stompjs
等 STOMP 客户端会将较大的 STOMP 消息在 16K 边界处分割,并将其作为多个 WebSocket 消息发送,这需要服务器缓冲并重新组装。
Spring 对 STOMP-over-WebSocket 的支持实现了这一点,因此应用可以配置 STOMP 消息的最大大小,而不受 WebSocket 服务器特定消息大小的影响。请注意,WebSocket 消息大小在必要时会自动调整,以确保它们至少可以承载 16K 的 WebSocket 消息。
以下示例显示了一种可能的配置
-
Java
-
Kotlin
-
Xml
@Configuration
@EnableWebSocketMessageBroker
public class MessageSizeLimitWebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(128 * 1024);
}
// ...
}
@Configuration
@EnableWebSocketMessageBroker
class MessageSizeLimitWebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun configureWebSocketTransport(registration: WebSocketTransportRegistration) {
registration.setMessageSizeLimit(128 * 1024)
}
// ...
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
https://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker>
<websocket:transport message-size="131072" />
<!-- ... -->
</websocket:message-broker>
</beans>
关于扩展的一个重要点涉及使用多个应用实例。目前,使用 simple broker 无法实现这一点。但是,当您使用功能齐全的 broker(如 RabbitMQ)时,每个应用实例都连接到 broker,并且从一个应用实例广播的消息可以通过 broker 广播到通过任何其他应用实例连接的 WebSocket 客户端。