当前位置: 首页 > article >正文

spring 配置websocket

在 Spring Boot 中使用 Kotlin 配置 WebSocket 的完整流程如下(包含基础配置、安全增强和性能优化):


一、添加依赖 (build.gradle.ktspom.xml)

// build.gradle.kts
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-websocket")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin") // JSON 支持
}

二、基础 WebSocket 配置

1. 启用 WebSocket 支持
@Configuration
@EnableWebSocket
class WebSocketConfig : WebSocketConfigurer {

    @Autowired
    lateinit var myWebSocketHandler: MyWebSocketHandler

    @Autowired
    lateinit var handshakeInterceptor: AuthHandshakeInterceptor

    override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) {
        registry.addHandler(myWebSocketHandler, "/ws")
            .addInterceptors(handshakeInterceptor)
            .setAllowedOrigins("*") // 生产环境应限制域名
    }
}

三、核心组件实现

1. WebSocket 消息处理器
@Component
class MyWebSocketHandler : TextWebSocketHandler() {

    private val sessions = ConcurrentHashMap<String, WebSocketSession>()
    private val logger = LoggerFactory.getLogger(this::class.java)

    // 连接建立
    override fun afterConnectionEstablished(session: WebSocketSession) {
        val userId = session.attributes["userId"] as? String
        userId?.let {
            sessions[it] = session
            logger.info("User $it connected, total: ${sessions.size}")
        } ?: run {
            session.close(CloseStatus.BAD_DATA)
        }
    }

    // 处理文本消息
    override fun handleTextMessage(session: WebSocketSession, message: TextMessage) {
        val payload = message.payload
        logger.debug("Received message: $payload")
        
        // 示例:广播消息
        sessions.values.forEach { 
            it.sendMessage(TextMessage("Broadcast: $payload"))
        }
    }

    // 连接关闭
    override fun afterConnectionClosed(session: WebSocketSession, status: CloseStatus) {
        sessions.values.remove(session)
        logger.info("Connection closed: ${status.reason}")
    }

    // 主动推送方法
    fun sendToUser(userId: String, message: String) {
        sessions[userId]?.sendMessage(TextMessage(message))
    }
}

2. 握手拦截器(安全校验)
@Component
class AuthHandshakeInterceptor : HandshakeInterceptor {

    override fun beforeHandshake(
        request: ServerHttpRequest,
        response: ServerHttpResponse,
        wsHandler: WebSocketHandler,
        attributes: MutableMap<String, Any>
    ): Boolean {
        // 1. 校验 Token
        val token = request.uri.query?.split("token=")?.get(1)
        if (!validateToken(token)) {
            response.statusCode = HttpStatus.UNAUTHORIZED
            return false
        }

        // 2. 获取用户信息
        val userId = parseUserIdFromToken(token)
        attributes["userId"] = userId
        
        // 3. 记录握手日志
        logHandshake(request.remoteAddress?.hostName)
        return true
    }

    private fun validateToken(token: String?): Boolean {
        // 实现 JWT 校验逻辑
        return token?.startsWith("valid_") == true
    }
}

四、客户端连接示例(JavaScript + Kotlin)

1. Web 前端连接
const socket = new WebSocket(`ws://${location.host}/ws?token=valid_123`);

socket.onmessage = (event) => {
  console.log('Received:', event.data);
};

// 发送心跳包保持连接
setInterval(() => {
  socket.send(JSON.stringify({ type: "heartbeat" }));
}, 30000);
2. Android 客户端(Kotlin)
class WebSocketClient(url: String) : WebSocketListener() {
    private val client = OkHttpClient()
    private var ws: WebSocket? = null

    init {
        val request = Request.Builder().url(url).build()
        ws = client.newWebSocket(request, this)
    }

    override fun onMessage(webSocket: WebSocket, text: String) {
        println("Received: $text")
    }

    fun sendMessage(msg: String) {
        ws?.send(msg)
    }
}

五、高级配置

1. 消息压缩配置
@Bean
fun webSocketContainer(): ServletServerContainerFactoryBean {
    return ServletServerContainerFactoryBean().apply {
        setMaxTextMessageBufferSize(8192)
        setMaxBinaryMessageBufferSize(8192)
        setAsyncSendTimeout(30000L) // 30秒异步发送超时
    }
}
2. 集群支持(Redis 广播)
@Configuration
@EnableRedisRepositories
class RedisPubSubConfig {

    @Bean
    fun redisTemplate(connectionFactory: RedisConnectionFactory): RedisTemplate<String, String> {
        return RedisTemplate<String, String>().apply {
            setConnectionFactory(connectionFactory)
        }
    }

    @Bean
    fun topicListenerAdapter(handler: MessageListener): ChannelTopic {
        return ChannelTopic("websocket-messages")
    }
}

六、监控与调试

1. 端点监控
@RestController
class WebSocketMetricsController(
    private val handler: MyWebSocketHandler
) {

    @GetMapping("/metrics/websocket")
    fun getMetrics(): Map<String, Any> {
        return mapOf(
            "activeConnections" to handler.getSessionCount(),
            "lastMessageTime" to handler.getLastActivity()
        )
    }
}
2. 日志配置 (logback-spring.xml)
<logger name="org.springframework.web.socket" level="DEBUG"/>
<logger name="com.example.websocket" level="TRACE"/>

七、常见问题解决方案

问题现象解决方案
连接频繁断开添加心跳机制,调整 setAsyncSendTimeout
跨域失败精确配置 .setAllowedOrigins("https://your-domain.com")
消息顺序错乱使用 @SendToUser(destination = "/queue", broadcast = false) 点对点发送
内存泄漏定期检查 sessions Map,添加连接超时清理逻辑
高并发时性能下降启用异步消息处理,使用 Redis Pub/Sub 分流消息

八、安全增强建议

  1. 启用 WSS 协议

    # Nginx 配置示例
    location /ws {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_ssl_protocols TLSv1.2 TLSv1.3;
    }
    
  2. 限流防护

    @Bean
    fun webSocketRateLimiter(): WebSocketHandlerDecoratorFactory {
        return object : WebSocketHandlerDecoratorFactory {
            override fun decorate(handler: WebSocketHandler): WebSocketHandler {
                val rateLimiter = RateLimiter.create(100) // 100次/秒
                return object : WebSocketHandlerDecorator(handler) {
                    override fun handleMessage(session: WebSocketSession, message: WebSocketMessage<*>) {
                        if (!rateLimiter.tryAcquire()) {
                            session.close(CloseStatus.POLICY_VIOLATION)
                            return
                        }
                        super.handleMessage(session, message)
                    }
                }
            }
        }
    }
    

九、性能测试建议

  1. 使用 JMeter 压测

    <!-- WebSocket 压测计划示例 -->
    <WebSocketSampler>
      <connectTime>5000</connectTime>
      <responseTimeout>10000</responseTimeout>
      <payload>{ "type": "stress", "data": "test" }</payload>
    </WebSocketSampler>
    
  2. 监控指标
    • 单节点最大连接数
    • 消息往返延迟 (RTT)
    • 内存占用增长率

通过以上配置,可以实现一个高性能、安全可靠的企业级 WebSocket 服务,支持从开发到生产的全生命周期管理。


http://www.kler.cn/a/592313.html

相关文章:

  • 好数 第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组
  • 5.2 Alpha to coverage in Depth
  • MySQL 调优
  • Vue的watchEffect的追踪逻辑
  • Docker 内部通信(网络)
  • BGP 路由选路、负载分担与发布策略
  • Android7 Input(一)Android Input服务初始化
  • Wireshark 远程 tcpdump使用配置
  • YOLOv11 目标检测
  • C程序设计(第五版)及其参考解答,附pdf
  • Android开发中的Native 调试
  • Python Matplotlib面试题精选及参考答案
  • 【Linux网络-数据链路层】以太网(以太网帧格式|MAC地址+模拟一次性局域网通信+MTU)+ARP协议
  • WebSocket 中的条件竞争漏洞 -- UTCTF Chat
  • 解决本地pycharm项目不识别anaconda的问题
  • 【Linux】system V消息队列,信号量
  • 【大模型实战篇】多模态推理模型Skywork-R1V
  • 启用 colcon的命令自动补全功能,适用于 bash终端
  • 当底层硬盘老旧时,如何限制Linux服务器和Windows服务的IOPS?
  • 【一起来学kubernetes】19、Pod使用详解