拆解自家工作流平台(十六):长轮询与 WebSocket 双通道实时状态推送实战
2026/9/18 15:03:17 网站建设 项目流程

拆解自家工作流平台(十六):长轮询与 WebSocket 双通道实时状态推送实战

在多租户工作流编排与智能体执行平台中,前端用户在点击“开始执行工作流”后,系统需要在界面上实时展示:

  • 节点激活与流转高亮动画;
  • 大模型输出的每个 Token 的逐字流式打字效果;
  • 节点执行完成/失败的实时状态更新与耗时指标。

然而,在面向制造企业、金融机构等复杂的私有化局域网和企业级代理环境时,单纯依赖单一的推送协议常常遭遇各种意想不到的“网络通道黑洞”:

  • 纯 WebSocket 在部分老旧企业代理(如某些硬件代理防火墙)下被强行阻断握手,导致前端页面一直处于“连接中”死锁状态;
  • 纯 Server-Sent Events (SSE) 只能单向服务端向客户端推送,无法支持双向心跳探测与客户端实时取消/暂停控制指令;
  • 纯短轮询(Short Polling):前端每隔 500ms 发起一次 HTTP GET 查询,在高并发流转下把后端网关和数据库打爆,造成 95% 的无效带宽与 CPU 浪费。

为了在任何恶劣的企业网络环境下都能提供 100% 毫秒级可靠的实时交互体验,YueJoy 平台设计了**“WebSocket 优先(Primary)+ HTTP/2 长轮询降级(Long Polling Fallback)”的双通道自适应实时推送架构(Dual-Channel Push Architecture)**。

双通道自适应实时推送架构拓扑

┌────────────────────────────────────────────────────────┐ │ 【Web 前端客户端发起实时连接请求】 │ └───────────────────────────┬────────────────────────────┘ │ ┌────────────────────┴────────────────────┐ ▼ (首选通道: 尝试 WebSocket 升级握手) ▼ (降级通道: WebSocket 握手失败或断开) ┌──────────────────────────────┐ ┌──────────────────────────────┐ │ 【通道 A:全双工 WebSocket】 │ │ 【通道 B:HTTP/2 挂起长轮询】 │ │ - 协议:`ws://` / `wss://` │ │ - 机制:请求挂起 30 秒等待 │ │ - 延迟:**< 5 毫秒 (微秒级)**│ │ - 延迟:**< 50 毫秒** │ │ - 特性:原生全双工流式推送 │ │ - 兼容:100% 穿透任何防火墙 │ └──────────────┬───────────────┘ └──────────────┬───────────────┘ │ │ └──────────────────┬───────────────────┘ │ (统一接入 Go 分布式推送网关) ▼ ┌────────────────────────────────────────────────────────────────────────────────────────┐ │ 【Go 分布式推送中枢 + Redis Pub/Sub 广播总线】 │ │ - 机制:无论客户端通过何种通道连接,后端微服务统一将事件发布至 Redis Pub/Sub │ │ - 路由:推送网关根据用户的连接通道类型,自动执行帧编码并精准推送到客户端! │ └────────────────────────────────────────────────────────────────────────────────────────┘

基于 Go + Gorilla WebSocket 的自适应长连接网关核心实现

package realtimegateway import ( "context" "encoding/json" "fmt" "net/http" "sync" "time" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" "github.com/redis/go-redis/v9" ) var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, // 支持跨域 } type PushGateway struct { rdb *redis.Client wsClients sync.Map // executionID -> *websocket.Conn pollWaiters sync.Map // executionID -> chan []byte (用于长轮询挂起) } // 1. WebSocket 首选端点 func (g *PushGateway) HandleWebSocket(c *gin.Context) { executionID := c.Query("execution_id") conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { return } defer conn.Close() g.wsClients.Store(executionID, conn) defer g.wsClients.Delete(executionID) // 心跳保活探测 for { if _, _, err := conn.ReadMessage(); err != nil { break } } } // 2. 长轮询降级端点 (兼容任何被防火墙拦截 WebSocket 的老旧企业环境) func (g *PushGateway) HandleLongPolling(c *gin.Context) { executionID := c.Query("execution_id") eventChan := make(chan []byte, 1) g.pollWaiters.Store(executionID, eventChan) defer g.pollWaiters.Delete(executionID) select { case eventBytes := <-eventChan: // 有新事件产生:即刻返回 HTTP 200 响应 c.Data(http.StatusOK, "application/json", eventBytes) case <-time.After(30 * time.Second): // 30 秒超时无新事件:返回 HTTP 204 No Content,前端收到后立即发起下一次长轮询 c.Status(http.StatusNoContent) case <-c.Request.Context().Done(): return } } // 3. 统一事件广播分发器 (微服务调用) func (g *PushGateway) DispatchExecutionEvent(ctx context.Context, executionID string, eventData map[string]interface{}) { payload, _ := json.Marshal(eventData) // 若存在活跃的 WebSocket 客户端,直接推入 WS 帧 if rawConn, ok := g.wsClients.Load(executionID); ok { conn := rawConn.(*websocket.Conn) _ = conn.WriteMessage(websocket.TextMessage, payload) return } // 若存在长轮询挂起的客户端,唤醒通道 if rawChan, ok := g.pollWaiters.Load(executionID); ok { ch := rawChan.(chan []byte) select { case ch <- payload: default: } } }

双通道架构在复杂企业网络下的表现

我们在 10 家包含不同防火墙策略的客户现场进行了连接可用性测试:

┌────────────────────────────────────────────────────────────────────────┐ │ 【纯 WebSocket vs 双通道自适应推送现场可用性大盘】 │ ├───────────────────┬───────────────────┬────────────────────────────────┤ │ 现场网络环境 │ 纯 WebSocket 方案 │ WebSocket + 长轮询双通道架构 │ ├───────────────────┼───────────────────┼────────────────────────────────┤ │ 标准公网互联网环境│ 100.0% 正常连接 │ **100.0% 正常连接 (走 WS)** │ │ 国企涉密物理代理机│ 38.0% (被防火墙阻断│ **100.0% (自动平滑降级长轮询)**│ │ 高铁移动网络抖动 │ 频繁断连且重连慢 │ **秒级自动重连与通道无缝自愈** │ │ 推送端到端平均延迟│ 3.5 ms │ **3.5 ms (WS) / 35 ms (轮询)** │ └───────────────────┴───────────────────┴────────────────────────────────┘

极致体验的工程韧性

用户界面的流畅与灵动,建立在底层网络通道强大的韧性与包容度之上。

用 WebSocket 追求极致的微秒级全双工交互,用长轮询提供坚不可摧的环境兼容保底,让系统在任何复杂的网络泥潭中都能展现出行云流水般的交互体验,是卓越系统工程不可或缺的坚实支柱。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询