Skip to content

实时通信

基于 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_HOST0.0.0.0监听地址
SSE_PORT8001监听端口,不可与 API 端口重复
SSE_WORKER_NUM4Worker 进程数

本地开发

启动 API 服务

bash
php think run

启动 SSE 服务

bash
php bin/sse_server.php start

Windows 下 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.target
bash
systemctl daemon-reload
systemctl enable youlai-sse
systemctl start youlai-sse
systemctl status youlai-sse

API 服务同步配置

youlai-api.service 参照上述格式,替换 ExecStart/Stopthink 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 在线状态

下一步

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