Skip to content

实时通信

youlai-admin 使用 SSE(Server-Sent Events)实现服务器到客户端的实时推送。

为什么选择 SSE

对比项SSEWebSocket
通信方向单向(服务端→客户端)双向
协议HTTPWS/WSS
断线重连浏览器自动需手动实现
适用场景消息推送、通知聊天、游戏

youlai-admin 的场景(字典同步、在线人数)只需要服务端推送,SSE 更简单。

架构

┌─────────────┐     HTTP GET      ┌─────────────┐
│   前端       │ ───────────────→ │   后端       │
│  useSse     │                   │  SSE 控制器  │
│             │ ←─────────────── │             │
└─────────────┘    EventStream    └─────────────┘


                                    ┌─────────────┐
                                    │   Redis     │
                                    │  Pub/Sub    │
                                    └─────────────┘

前端实现

useSse Composable

typescript
import { useSse } from "@/composables";

const { isConnected, connect, on } = useSse();

// 建立连接
onMounted(() => connect());

// 订阅事件
on("dict-change", (data) => {
  console.log("字典已更新:", data.dictCode);
});

内置事件

事件名说明数据结构
dict-change字典变更{ dictCode: string }
online-count在线人数{ count: number }

后端实现

Java(Spring Boot)

java
@GetMapping("/api/v1/sse/connect")
public SseEmitter connect() {
    SseEmitter emitter = new SseEmitter(0L);
    // 注册到 SSE 管理器
    sseManager.register(emitter);
    return emitter;
}

NestJS

typescript
@Sse('connect')
connect(): Observable<MessageEvent> {
  return new Observable(subscriber => {
    sseService.register(subscriber)
  })
}

使用场景

字典同步

后端字典变更时,推送通知到所有在线客户端,客户端清除缓存并重新加载。

typescript
// composables/useDictSync.ts
on("dict-change", (data) => {
  dictStore.clearCache(data.dictCode);
});

在线人数

实时显示当前在线用户数。

typescript
// composables/useOnlineCount.ts
on("online-count", (data) => {
  onlineCount.value = data.count;
});

断线重连

useSse 内置指数退避重连:

重试次数等待时间
15s
210s
320s
4+120s(上限)

下一步

基于 MIT 许可发布 · 由 ❤️ 和 ☕ 驱动 · 支持作者