feat(websocket): 添加 Undertow WebSocket 配置优化

- 新增 UndertowWebSocketConfig 类解决启动警告
- 配置 WebSocket 缓冲池大小及线程本地缓存
- 重命名 WsConfig 为 WebSocketEndpointConfig
- 移除旧的 WsFactory 配置类
- 优化 WebSocket 部署信息自定义逻辑
This commit is contained in:
2025-10-31 14:45:45 +08:00
parent 237d664e8a
commit ad8157258e
5 changed files with 124 additions and 75 deletions
@@ -0,0 +1,41 @@
package cn.odboy.framework.websocket.config;
import io.undertow.server.DefaultByteBufferPool;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
/**
* 解决启动io.undertow.websockets.jsr UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used的警告
*
* @author odboy
* @date 2025-10-30
*/
@Component
public class UndertowWebSocketConfig implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
private int calculateThreadLocalCacheSize(int processorCount) {
// 每个I/O线程缓存2-4个缓冲区
return Math.max(2, processorCount / 2);
}
private int calculateMaxPoolSize(int processorCount) {
// 基础值 + 根据CPU核心数调整
int baseSize = 100;
return baseSize + (processorCount * 20);
}
@Override
public void customize(UndertowServletWebServerFactory factory) {
int processorCount = Runtime.getRuntime().availableProcessors();
int bufferSize = 1024;
int maxPoolSize = calculateMaxPoolSize(processorCount);
int threadLocalCacheSize = calculateThreadLocalCacheSize(processorCount);
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, bufferSize, maxPoolSize, threadLocalCacheSize));
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
});
}
}
@@ -19,9 +19,14 @@ package cn.odboy.framework.websocket.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 自动注册使用了 @ServerEndpoint 注解声明的 WebSocket 端点对象
*
* @author odboy
* @date 2025-10-30
*/
@Configuration
public class WsConfig {
public class WebSocketEndpointConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
@@ -0,0 +1,41 @@
package cn.odboy.framework.websocket.config;
import io.undertow.server.DefaultByteBufferPool;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
/**
* 解决启动io.undertow.websockets.jsr UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used的警告
*
* @author odboy
* @date 2025-10-30
*/
@Component
public class UndertowWebSocketConfig implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
private int calculateThreadLocalCacheSize(int processorCount) {
// 每个I/O线程缓存2-4个缓冲区
return Math.max(2, processorCount / 2);
}
private int calculateMaxPoolSize(int processorCount) {
// 基础值 + 根据CPU核心数调整
int baseSize = 100;
return baseSize + (processorCount * 20);
}
@Override
public void customize(UndertowServletWebServerFactory factory) {
int processorCount = Runtime.getRuntime().availableProcessors();
int bufferSize = 1024;
int maxPoolSize = calculateMaxPoolSize(processorCount);
int threadLocalCacheSize = calculateThreadLocalCacheSize(processorCount);
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, bufferSize, maxPoolSize, threadLocalCacheSize));
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
});
}
}
@@ -1,30 +1,35 @@
/*
* Copyright 2021-2025 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.websocket.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WsConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
/*
* Copyright 2021-2025 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.websocket.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 自动注册使用了 @ServerEndpoint 注解声明的 WebSocket 端点对象
*
* @author odboy
* @date 2025-10-30
*/
@Configuration
public class WebSocketEndpointConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
@@ -1,43 +0,0 @@
/*
* Copyright 2021-2025 Odboy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.odboy.framework.websocket.config;
import io.undertow.server.DefaultByteBufferPool;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
/**
* 解决启动io.undertow.websockets.jsr UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used的警告
*
* @date 2024-06-07
*/
@Component
public class WsFactory implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 1024));
deploymentInfo.addServletContextAttribute(
"io.undertow.websockets.jsr.WebSocketDeploymentInfo",
webSocketDeploymentInfo);
});
}
}