性能

在性能方面,没有一劳永逸的解决方案。许多因素会影响性能,包括消息的大小和数量,应用程序方法是否执行需要阻塞的工作,以及外部因素(如网络速度和其他问题)。本节的目标是概述可用的配置选项,并就如何推理扩展提供一些思考。

在消息应用程序中,消息通过由线程池支持的通道进行异步执行。配置此类应用程序需要对通道和消息流有充分的了解。因此,建议查阅消息流

显而易见的起点是配置支持clientInboundChannelclientOutboundChannel的线程池。默认情况下,两者都配置为可用处理器数量的两倍。

如果带注解方法中的消息处理主要是CPU密集型的,clientInboundChannel的线程数应保持接近处理器数量。如果它们所做的工作更多是IO密集型的,需要阻塞或等待数据库或其他外部系统,则可能需要增加线程池大小。

ThreadPoolExecutor有三个重要属性:核心线程池大小、最大线程池大小以及用于存储没有可用线程的任务的队列容量。

一个常见的误解是,配置核心池大小(例如,10)和最大池大小(例如,20)会产生一个包含10到20个线程的线程池。实际上,如果容量保持其默认值Integer.MAX_VALUE,线程池永远不会超过核心池大小,因为所有额外的任务都会排队。

请参阅ThreadPoolExecutor的javadoc以了解这些属性如何工作以及各种排队策略。

clientOutboundChannel方面,主要是向WebSocket客户端发送消息。如果客户端在快速网络上,线程数应保持接近可用处理器数量。如果它们速度慢或带宽低,它们消耗消息的时间会更长,并对线程池造成负担。因此,增加线程池大小变得必要。

虽然clientInboundChannel的工作负载是可能预测的——毕竟,它基于应用程序所做的事情——但如何配置"clientOutboundChannel"则更难,因为它基于应用程序无法控制的因素。因此,还有两个额外属性与消息发送相关:sendTimeLimitsendBufferSizeLimit。您可以使用这些方法配置允许发送操作花费的时间以及向客户端发送消息时可以缓冲的数据量。

一般而言,在任何给定时间,只能使用单个线程向客户端发送消息。同时,所有额外的消息都会被缓冲,您可以使用这些属性来决定允许发送消息花费多长时间以及在此期间可以缓冲多少数据。有关重要的附加详细信息,请参阅javadoc和XML schema文档。

以下示例显示了一种可能的配置

  • 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>

关于扩展的一个重要点涉及使用多个应用程序实例。目前,您无法使用简单的代理实现这一点。但是,当您使用功能齐全的代理(如 RabbitMQ)时,每个应用程序实例都连接到代理,并且从一个应用程序实例广播的消息可以通过代理广播到通过任何其他应用程序实例连接的 WebSocket 客户端。

© . This site is unofficial and not affiliated with VMware.