效能

效能方面沒有萬靈藥。許多因素影響效能,包括訊息的大小和數量、應用方法是否執行需要阻塞的工作,以及外部因素(如網路速度和其他問題)。本節旨在概述可用的配置選項,並提供關於如何考慮擴充套件的一些想法。

在訊息應用中,訊息透過通道傳遞以進行非同步執行,這些通道由執行緒池支援。配置這樣的應用需要很好地瞭解通道和訊息流。因此,建議查閱訊息流

顯而易見的起點是配置支援 clientInboundChannelclientOutboundChannel 的執行緒池。預設情況下,兩者都配置為可用處理器數量的兩倍。

如果在註解方法中處理訊息主要是 CPU 密集型工作,則 clientInboundChannel 的執行緒數應保持接近處理器數量。如果它們執行的工作更多是 IO 密集型,需要阻塞或等待資料庫或其他外部系統,則執行緒池大小可能需要增加。

ThreadPoolExecutor 有三個重要屬性:核心執行緒池大小、最大執行緒池大小以及佇列儲存沒有可用執行緒的任務的能力。

一個常見的困惑點是,配置核心池大小(例如 10)和最大池大小(例如 20)會導致一個擁有 10 到 20 個執行緒的執行緒池。實際上,如果容量保留其預設值 Integer.MAX_VALUE,則執行緒池永遠不會超過核心池大小,因為所有附加任務都將被排隊。

檢視 ThreadPoolExecutor 的 javadoc,瞭解這些屬性如何工作以及理解各種排隊策略。

clientOutboundChannel 側,主要是向 WebSocket 客戶端傳送訊息。如果客戶端處於快速網路中,執行緒數應保持接近可用處理器數量。如果它們速度較慢或頻寬較低,則需要更長時間來消費訊息,並給執行緒池帶來負擔。因此,增加執行緒池大小變得必要。

雖然 clientInboundChannel 的工作負載是可以預測的——畢竟它基於應用做什麼——但如何配置 "clientOutboundChannel" 更難,因為它基於應用無法控制的因素。因此,有兩個附加屬性與訊息傳送相關:sendTimeLimitsendBufferSizeLimit。您可以使用這些方法配置傳送操作允許花費多長時間以及向客戶端傳送訊息時可以緩衝多少資料。

一般想法是,在任何給定時間,只能使用單個執行緒向客戶端傳送訊息。同時,所有附加訊息都會被緩衝,您可以使用這些屬性來決定傳送訊息允許花費多長時間以及在此期間可以緩衝多少資料。檢視 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 客戶端。