This commit is contained in:
2026-08-05 17:38:29 +08:00
parent e831ce810b
commit 98b60c333a
5 changed files with 145 additions and 4 deletions

79
worker/websocket.php Normal file
View File

@@ -0,0 +1,79 @@
<?php
/**
* Workerman 广播服务
* ------------------------------------------------------------
* 启动: php worker/websocket.php start
* 停止: 前台运行按 Ctrl+C 即可Windows 不支持 stop 命令)
*
* 端口:
* 2346 websocket 端口,员工前端长连接(只推送,不做业务)
* 2347 http 触发端口,仅监听 127.0.0.1,供 ThinkPHP 内部调用
*
* 触发方式POST http://127.0.0.1:2347/push
* body: {"action":"create","ticket_id":123}
*
* 注意:
* - Workerman 在 Windows 上不支持一个文件声明多个 worker
* 因此这里采用官方推荐的「单 worker + onWorkerStart 动态 listen()」方案,
* 两个端口跑在同一个进程内,共享在线连接表。
* - 部署到 Linux 后此写法同样适用,可额外增加 Worker::count 多进程。
*/
use Workerman\Worker;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/../vendor/autoload.php';
// 当前在线前端连接connection id => connection
$clients = [];
// ---------- 主 workerWebSocket 服务(员工前端连接) ----------
$wsWorker = new Worker('websocket://0.0.0.0:2346');
$wsWorker->name = 'ticket-broadcast';
$wsWorker->onConnect = function ($connection) use (&$clients) {
$connection->cid = spl_object_id($connection);
$clients[$connection->cid] = $connection;
echo '[' . date('Y-m-d H:i:s') . "] client connected, online: " . count($clients) . PHP_EOL;
};
$wsWorker->onClose = function ($connection) use (&$clients) {
if (isset($clients[$connection->cid])) {
unset($clients[$connection->cid]);
}
echo '[' . date('Y-m-d H:i:s') . "] client closed, online: " . count($clients) . PHP_EOL;
};
// ---------- 进程启动后追加 HTTP 触发端口(仅本机) ----------
$wsWorker->onWorkerStart = function ($worker) use (&$clients) {
$httpWorker = new Worker('http://127.0.0.1:2347');
$httpWorker->name = 'ticket-push-trigger';
$httpWorker->onMessage = function ($connection, Request $request) use (&$clients) {
if ($request->method() === 'POST' && $request->path() === '/push') {
$data = json_decode($request->rawBody(), true) ?: [];
$payload = json_encode([
'type' => 'ticket_changed',
'action' => isset($data['action']) ? (string)$data['action'] : 'update',
'ticket_id' => isset($data['ticket_id']) ? (int)$data['ticket_id'] : null,
], JSON_UNESCAPED_UNICODE);
$sent = 0;
foreach ($clients as $client) {
$client->send($payload);
$sent++;
}
echo '[' . date('Y-m-d H:i:s') . "] push [{$payload}] to {$sent} clients" . PHP_EOL;
$connection->send('ok');
} else {
$connection->send('bad request');
}
};
// 同一进程内动态监听第二端口Windows 下多 worker 的限制的官方解法)
$httpWorker->listen();
};
Worker::runAll();