共计 1691 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点分析
传统人机交互系统通常采用 HTTP 轮询或长轮询方式实现前后端通信,这种方式在高并发场景下会暴露几个典型问题:

- 资源消耗大 :HTTP 轮询会产生大量无效请求,服务器需要频繁处理连接建立和断开
- 实时性差 :消息传递延迟通常在秒级,难以满足即时交互需求
- 状态同步困难 :多终端同时操作时容易出现数据不一致
- 扩展性差 :单机连接数受端口数量限制,难以水平扩展
架构设计思路
通信协议选型对比
- RESTful HTTP:
- 优点:实现简单,兼容性好
-
缺点:单向通信,实时性差
-
WebSocket:
- 优点:全双工通信,低延迟
-
缺点:需要维护长连接状态
-
gRPC:
- 优点:高性能二进制协议
- 缺点:浏览器支持有限
最终选择 WebSocket 作为基础协议,配合 STOMP 子协议实现消息路由。
Agent 核心组件设计
sequenceDiagram
participant Client
participant Gateway
participant AgentService
participant MessageQueue
Client->>Gateway: 建立 WebSocket 连接
Gateway->>AgentService: 注册新 Agent
AgentService->>MessageQueue: 订阅主题
loop 消息处理
Client->>Gateway: 发送操作指令
Gateway->>MessageQueue: 发布消息
MessageQueue->>AgentService: 推送消息
AgentService->>Gateway: 返回执行结果
Gateway->>Client: 推送状态更新
end
状态同步策略
- 乐观锁 :通过版本号解决冲突,适合低频修改场景
- CRDT:无冲突复制数据类型,适合分布式环境
- 操作转换 :实时协作场景常用方案
代码实现细节
WebSocket 基础配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/agent")
.setAllowedOrigins("*")
.withSockJS();}
}
消息压缩配置
spring:
websocket:
compression:
enabled: true
min-size: 2KB
strategies: [permessage-deflate]
性能优化实践
序列化方案对比
| 方案 | 吞吐量 (msg/s) | 平均延迟 (ms) | 带宽占用 |
|---|---|---|---|
| JSON | 12,000 | 45 | 100% |
| Protobuf | 28,000 | 18 | 35% |
| MessagePack | 22,000 | 25 | 60% |
Linux 内核调优
# 启用 TIME_WAIT 连接重用
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
# 增加最大打开文件数
echo "* soft nofile 100000" >> /etc/security/limits.conf
避坑指南
- 消息幂等 :每条消息必须携带唯一 ID,服务端维护已处理 ID 集合
- 内存泄漏 :定期检查 WebSocketSession 是否正常关闭
- 协议兼容 :新版本必须支持旧版消息格式至少 3 个迭代周期
总结与思考
通过事件驱动架构和 WebSocket 协议,我们构建了高实时性的人机交互系统。在实际项目中还需要考虑:
- 如何设计支持百万级 Agent 的横向扩展架构?
- 在弱网环境下如何保证操作流畅性?
- 如何平衡实时性和数据一致性要求?
这些问题的解决方案可能需要结合具体业务场景进行设计。
正文完
