实时通信
基于 Workerman 独立 SSE 服务实现服务端推送,通过 Redis 队列实现 API 进程与 SSE 进程的跨进程通信。
架构概览
浏览器 ──── Nginx(:80) ──── /api/v1/sse/* ──── SSE 服务(:8001)
└── /api/* ──── API 服务(:8000)核心设计:SSE 长连接与 API 分离到独立 Workerman 进程,通过 Redis List 跨进程通信。
使用场景
- 通知公告推送
- 在线人数统计
- 字典/缓存实时同步
文件结构
extend/sse/
├── SseWorkerServer.php # Workerman SSE 服务器
├── SseEventPublisher.php # Redis 事件发布器
├── SseService.php # 业务调用入口
└── SseEmitter.php # SSE 连接封装环境配置
在 .env 中添加 SSE 相关配置:
bash
# SSE 服务配置
SSE_HOST = 0.0.0.0
SSE_PORT = 8001
SSE_WORKER_NUM = 4| 配置项 | 默认值 | 说明 |
|---|---|---|
SSE_HOST | 0.0.0.0 | 监听地址 |
SSE_PORT | 8001 | 监听端口,不可与 API 端口重复 |
SSE_WORKER_NUM | 4 | Worker 进程数 |
本地开发
启动 API 服务
bash
php think run启动 SSE 服务
bash
php bin/sse_server.php startWindows 下 Worker 数自动设为 1。
验证连接
bash
# 健康检查
curl http://127.0.0.1:8001/health
# SSE 连接测试(替换为实际 token)
curl -N -H "Authorization: Bearer <token>" http://127.0.0.1:8001/api/v1/sse/connect生产部署
systemd 服务
创建 /etc/systemd/system/youlai-sse.service:
ini
[Unit]
Description=YouLai SSE Server
After=network.target redis.service
[Service]
Type=forking
User=www
Group=www
WorkingDirectory=/opt/youlai-think
ExecStart=/usr/bin/php bin/sse_server.php start -d
ExecStop=/usr/bin/php bin/sse_server.php stop
ExecReload=/usr/bin/php bin/sse_server.php restart
Restart=on-failure
RestartSec=5
EnvironmentFile=/opt/youlai-think/.env
[Install]
WantedBy=multi-user.targetbash
systemctl daemon-reload
systemctl enable youlai-sse
systemctl start youlai-sse
systemctl status youlai-sseAPI 服务同步配置
youlai-api.service 参照上述格式,替换 ExecStart/Stop 为 think worker:server 命令。
Nginx 配置
前端统一使用一个端口访问,通过 Nginx 按 URL 路径分发到不同后端服务:
nginx
server {
listen 80;
server_name youlai.tech;
# SSE 长连接 → 8001
location /api/v1/sse/ {
proxy_pass http://127.0.0.1:8001;
# SSE 必需配置
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 禁用缓冲,事件即时推送
proxy_buffering off;
proxy_cache off;
# 超时设置(与心跳间隔匹配)
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
# 普通 API → 8000
location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 前端静态资源
location / {
root /opt/youlai-admin/dist;
try_files $uri $uri/ /index.html;
}
}关键说明:
proxy_buffering off:禁止 Nginx 缓冲 SSE 响应,确保事件即时透传proxy_read_timeout 86400s:超时设为 24 小时,避免长连接被 Nginx 切断proxy_http_version 1.1+Connection '':保持 HTTP 长连接
事件通信机制
流向:业务代码 → SseService → Redis List → SSE Worker → 浏览器
事件主题:dict(字典变更)、online-count(在线人数)、system(系统消息)
业务调用方式
php
SseService::getInstance()->sendDictChange('gender'); // 字典变更通知
SseService::getInstance()->sendSystemMessage('系统维护通知'); // 系统消息广播
SseService::getInstance()->sendToUser('admin', 'notice', $data); // 点对点推送连接保护机制
| 保护策略 | 说明 |
|---|---|
| 全局连接数限制 | 默认最大 1000 个 SSE 连接 |
| 单用户连接数限制 | 默认每用户最多 3 个连接,超出踢掉最旧连接 |
| JWT 鉴权 | 连接时验证 Bearer Token |
| 心跳保活 | 每 30s 发送注释事件,检测连接存活 |
| 异常清理 | 连接断开时自动清理注册表和 Redis 在线状态 |
