性能
在性能方面,没有万能的解决方案。许多因素都会影响性能,包括消息的大小和数量、应用程序方法是否执行需要阻塞的工作以及外部因素(例如网络速度和其他问题)。本节的目的是概述可用的配置选项,并提供一些关于如何考虑扩展的思路。
在消息传递应用程序中,消息通过通道传递,以进行由线程池支持的异步执行。配置此类应用程序需要对通道和消息流有很好的了解。因此,建议您查看 消息流。
显然,首先要配置支持 clientInboundChannel
和 clientOutboundChannel
的线程池。默认情况下,这两个通道的配置都设置为可用处理器数量的两倍。
如果在带注释的方法中处理消息主要是 CPU 密集型,那么 clientInboundChannel
的线程数量应该保持接近处理器数量。如果它们执行的工作更多地是 I/O 密集型,并且需要阻塞或等待数据库或其他外部系统,则可能需要增加线程池大小。
一个常见的困惑是,配置核心池大小(例如,10)和最大池大小(例如,20)会导致一个具有 10 到 20 个线程的线程池。实际上,如果容量保留为其默认值 Integer.MAX_VALUE,则线程池永远不会超过核心池大小,因为所有额外的任务都会被排队。 请参阅 |
在 clientOutboundChannel
方面,它主要是关于将消息发送到 WebSocket 客户端。如果客户端位于快速网络上,则线程数量应该保持接近可用处理器数量。如果它们速度慢或带宽低,则它们需要更长时间才能使用消息,并给线程池带来负担。因此,有必要增加线程池大小。
虽然 clientInboundChannel
的工作负载是可以预测的——毕竟它取决于应用程序的行为——但如何配置 "clientOutboundChannel" 却更难,因为它取决于应用程序无法控制的因素。出于这个原因,与消息发送相关的两个附加属性是:sendTimeLimit
和 sendBufferSizeLimit
。您可以使用这些方法来配置发送消息允许花费的时间以及在发送消息时可以缓冲的数据量。
总体思路是,在任何给定时间,只有一个线程可以用于向客户端发送消息。同时,所有其他消息都会被缓冲,您可以使用这些属性来决定发送消息允许花费的时间以及在此期间可以缓冲的数据量。有关重要附加细节,请参阅 javadoc 和 XML 模式文档。
以下示例展示了一种可能的配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024);
}
// ...
}
以下示例展示了与前面示例等效的 XML 配置
<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 客户端(例如 stomp-js/stompjs
等)会在 16K 边界处拆分较大的 STOMP 消息,并将它们作为多个 WebSocket 消息发送,这需要服务器进行缓冲和重新组装。
Spring 的 STOMP-over-WebSocket 支持会执行此操作,因此应用程序可以配置 STOMP 消息的最大大小,而无需考虑 WebSocket 服务器特定的消息大小。请记住,WebSocket 消息大小会根据需要自动调整,以确保它们至少可以承载 16K 的 WebSocket 消息。
以下示例展示了一种可能的配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(128 * 1024);
}
// ...
}
以下示例展示了与前面示例等效的 XML 配置
<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>
关于扩展的一个重要点是使用多个应用程序实例。目前,您无法使用简单的代理来实现这一点。但是,当您使用功能齐全的代理(例如 RabbitMQ)时,每个应用程序实例都会连接到代理,并且从一个应用程序实例广播的消息可以通过代理广播到通过任何其他应用程序实例连接的 WebSocket 客户端。