Search by

adminmatrix / matrix_worker

bin94581222

Worker

Package info

gitee.com/adminmatrix/matrix_worker

pkg:composer/adminmatrix/matrix_worker

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

v1.0.2 2026-09-16 07:40 UTC

This package is not auto-updated.

Last update: 2026-09-16 07:42:10 UTC


README

ThinkPHP8 的 Workerman / GatewayWorker 常驻服务集成包——一条命令启动并管理 WebSocket 网关、TCP 服务、队列消费。

特性

  • 一条命令管理所有常驻服务php think workers [start|stop|restart|reload|status]
  • GatewayWorker 体系:Register 注册中心 + BusinessWorker 业务进程 + 多 Gateway 网关,多个 WebSocket 入口共享同一套业务进程
  • 多进程无连接隔离:内置 Gateway API(sendToUid / sendToGroup / sendToAll / bindUid / joinGroup),天然支持多进程、分布式部署
  • TCP 自定义协议服务:如物联网设备接入,业务继承 Handler 即可
  • 队列常驻消费:Workerman 进程内运行 think-queue 的 daemon 循环,相当于常驻内存版 php think queue:work --daemon
  • 开发热更新:前台启动自动监控 app / config 下 .php 变化,自动重载业务进程且客户端连接不断
  • 三层开关worker.enable 总开关 → 分组 enable → 项级 enable,任意粒度控制服务启停
  • 服务上下文:每次启动的服务清单(类型 / 监听 / 进程数 / 处理器)写入 runtime/worker/services.json
  • 零配置文件复制:主项目无 config/matrix_worker.php 时自动注入包内模板

环境要求

依赖版本
PHP>= 8.3
topthink/framework^8.1
workerman/gateway-worker^4.0

安装

composer require adminmatrix/matrix_worker

快速开始

1. 启动服务

php think workers          # 前台启动(调试)
php think workers start -d # 守护进程启动

启动后默认注册 6 个服务:

Register          text://127.0.0.1:1236      注册中心
business          none                       业务进程 -> Events
worker            websocket://0.0.0.0:2348   主网关(内部通讯 2000)
gateway           websocket://0.0.0.0:2347   组级默认网关(内部通讯 2100)
测试聊天服务       websocket://0.0.0.0:2346   额外网关(内部通讯 2200)
默认队列          none                       队列 default 消费

2. 前端连接

const ws = new WebSocket('ws://127.0.0.1:2346');
ws.onmessage = e => {
    const data = JSON.parse(e.data);
    if (data.type === 'ping') { ws.send('{"type":"pong"}'); return; } // 心跳回应(配置 pingInterval 后)
    console.log(data);
};
ws.onopen = () => ws.send('hello');
// 收到:{"type":"welcome","msg":"连接成功","client_id":"7f000001..."}
// 收到:{"type":"echo","msg":"hello"}

命令

命令说明
php think workers前台启动(调试模式)
php think workers start -d守护进程启动
php think workers stop停止服务
php think workers restart重启服务
php think workers reload平滑重启(重载业务代码)
php think workers status查看进程状态

配置

主项目无配置时自动使用包内模板;需要自定义时复制到主项目 config/matrix_worker.php

配置优先级:workers 项 > 分组 > 全局 worker

return [
    // 开发模式热更新(仅前台启动生效,守护进程 start -d 自动关闭)
    'monitor' => [
        'enable'   => true,               // 开关:false 时前台启动也不监控
        'interval' => 1,                  // 扫描间隔秒
        'paths'    => ['app', 'config'],  // 监控目录(相对主项目根目录)
    ],
    // 队列消费服务(不监听端口,常驻消费 think-queue)
    'queue' => [
        'enable' => true,
        'queue'  => 'default',      // 分组默认:监听的队列名
        'sleep'  => 3,              // 分组默认:空闲休眠秒数
        'count'  => 1,
        'workers' => [
            [
                'enable' => true,
                'name'   => '默认队列',
                'queue'  => 'default',   // 项缺省时用分组默认
            ],
        ],
    ],
    // 全局总开关 + 全局默认值(worker.enable = false 时所有服务都不注册)
    'worker' => [
        'enable' => true,
        'host'   => '0.0.0.0',
        'port'   => 2348,            // 默认主网关端口
        'count'  => 1,
    ],
    // GatewayWorker 体系(Register 注册中心 + BusinessWorker 业务进程 + 多 Gateway 网关)
    'gateway' => [
        'enable' => true,
        // Register 注册中心(Gateway / BusinessWorker 通过它互相发现)
        'register' => [
            'host' => '127.0.0.1',
            'port' => 1236,
        ],
        // BusinessWorker 业务进程(eventHandler 静态方法类,业务逻辑写这里)
        'business' => [
            'name'    => 'business',
            'count'   => 1,
            'handler' => 'adminmatrix\worker\websocket\Events',
        ],
        // 网关内部通讯
        'lanIp'     => '127.0.0.1',      // 内部通讯 IP(多机部署填内网 IP)
        'startPort' => 2000,             // 内部通讯起始端口(多网关自动按 100 错开)
        // 组级默认网关(始终注册)
        'name'      => 'gateway',
        'host'      => '0.0.0.0',
        'port'      => 2347,
        'count'     => 1,
        // 额外网关(多个 ws 入口,共享同一套 BusinessWorker 业务进程,
        // 业务逻辑统一写在 business.handler 指向的 Events 类,见「业务开发」)
        'workers' => [
            [
                'enable' => true,
                'name'   => '测试聊天服务',
                'host'   => '0.0.0.0',
                'port'   => 2346,
            ],
            // 完整可用字段(按需打开):
            // [
            //     'enable'               => true,                  // 项级开关(缺省视为开启)
            //     'name'                 => '客服服务',
            //     'host'                 => '0.0.0.0',
            //     'port'                 => 2350,
            //     'count'                => 1,                     // 进程数
            //     'handler'              => 'app\worker\Events',   // 独立业务事件类(缺省用 business.handler)
            //     'lanIp'                => '127.0.0.1',           // 内部通讯 IP(多机部署填内网 IP)
            //     'startPort'            => 2300,                  // 内部通讯起始端口(缺省自动按 100 错开)
            //     'pingInterval'         => 30,                    // 心跳间隔秒(> 0 开启心跳,0 不心跳)
            //     'pingNotResponseLimit' => 2,                     // 连续 N 个周期无上行消息则断开(0 只发不踢)
            //     'pingData'             => '{"type":"ping"}',     // 服务端下发的心跳包内容
            // ],
        ],
    ],
    // TCP 服务(多实例,自定义协议如物联网设备接入)
    'tcp' => [
        'enable' => false,
        'host'   => '0.0.0.0',
        'port'   => 2349,
        'count'  => 1,
        'workers' => [
            // 完整可用字段(按需打开,handler 继承 adminmatrix\worker\tcp\Handler):
            // [
            //     'enable'  => true,                              // 项级开关(缺省视为开启)
            //     'name'    => '设备接入',
            //     'host'    => '0.0.0.0',
            //     'port'    => 2351,
            //     'count'   => 1,                                 // 进程数
            //     'handler' => 'app\worker\tcp\DeviceHandler',     // 业务处理器
            // ],
        ],
    ],
];

开关层级

worker.enable = false        # 所有服务都不注册
├── gateway.enable = false   # GatewayWorker 体系整体不注册
│   └── workers[].enable     # 单个网关不注册
├── tcp.enable = false       # TCP 服务整体不注册
│   └── workers[].enable
└── queue.enable = false     # 队列消费整体不注册
    └── workers[].enable

业务开发

WebSocket 业务(Events 静态方法类)

业务逻辑写在 gateway.business.handler 指向的类里,静态方法,拿到的是 client_id(不是 connection 对象),通过 Gateway API 操作连接:

namespace app\worker;

use GatewayWorker\Lib\Gateway;

class Events
{
    public static function onConnect($client_id): void
    {
        Gateway::sendToClient($client_id, json_encode([
            'type'      => 'welcome',
            'msg'       => '连接成功',
            'client_id' => $client_id,
        ], JSON_UNESCAPED_UNICODE));
    }

    public static function onMessage($client_id, $message): void
    {
        $data = json_decode($message, true);
        switch ($data['type'] ?? '') {
            case 'bind':   // 绑定用户(多端登录自动合并)
                Gateway::bindUid($client_id, $data['uid']);
                break;
            case 'join':   // 加入房间
                Gateway::joinGroup($client_id, $data['room']);
                break;
            case 'say':    // 房间消息
                Gateway::sendToGroup($data['room'], $data['msg']);
                break;
            case 'all':    // 全局广播
                Gateway::sendToAll($data['msg']);
                break;
        }
    }

    public static function onClose($client_id): void {}
}

指向业务类:

'business' => [
    'handler' => 'app\worker\Events',
],

多网关不同业务(workers 项级 handler)

每个网关项可配独立 handler(业务事件类),包会为它创建专属 BusinessWorker 进程并固定路由——各网关业务完全隔离;不配 handler 的网关走默认 business.handler。多个网关配同一个 handler 时共享同一个业务进程:

'workers' => [
    [   // 不配 handler -> 走默认 business.handler(adminmatrix\worker\websocket\Events)
        'name' => '测试聊天服务',
        'port' => 2346,
    ],
    [   // 独立业务事件类 -> 专属 BusinessWorker 进程
        'name'    => '客服服务',
        'port'    => 2350,
        'handler' => 'app\worker\CustomerEvents',
    ],
],

CustomerEvents 与默认 Events 写法相同(静态方法 + Gateway API):

namespace app\worker;

use GatewayWorker\Lib\Gateway;

class CustomerEvents
{
    public static function onConnect($client_id): void
    {
        Gateway::sendToClient($client_id, json_encode([
            'type' => 'welcome', 'msg' => '客服服务连接成功',
        ], JSON_UNESCAPED_UNICODE));
    }

    public static function onMessage($client_id, $message): void
    {
        // 客服业务...
    }

    public static function onClose($client_id): void {}
}

心跳配置

网关项(或 gateway 组级)配置心跳,自动踢掉死连接:

'pingInterval'         => 30,                 // 每 30 秒向客户端下发一次 pingData
'pingNotResponseLimit' => 2,                  // 连续 2 个周期(60 秒)无上行消息则断开
'pingData'             => '{"type":"ping"}',  // 下发的心跳包内容

前端收到心跳包后回一条任意消息即可保活(推荐 {"type":"pong"}),见「前端连接」示例。

热更新(开发模式)

前台启动(php think workers)时自动开启文件监控,改 app / config 下的 .php 文件后约 1 秒自动生效,无需手动 reload,客户端连接不断

[monitor] 检测到文件变化,平滑重载业务进程(连接保持)...

原理:Gateway(持有客户端连接)和 Register 不参与 reload;reload 信号只重启业务进程(BusinessWorker / TCP)重新加载业务代码,客户端连接保持。Queue 消费进程不参与 reload(think-queue 的 daemon 循环不处理重载信号,队列代码变更请用 restart)。守护进程模式(start -d)自动关闭监控;监控目录 / 间隔见 monitor 配置。

注意:修改 config / Worker 启动逻辑相关代码仍需 php think workers restart(reload 只热更新业务代码)。

常用 Gateway API:

方法说明
Gateway::sendToClient($client_id, $msg)发给单个连接
Gateway::sendToUid($uid, $msg)发给用户(bindUid 后,多端全收)
Gateway::sendToGroup($group, $msg)发给分组(joinGroup 后)
Gateway::sendToAll($msg)全局广播
Gateway::bindUid($client_id, $uid)连接绑定用户
Gateway::joinGroup($client_id, $group)连接加入分组
Gateway::closeClient($client_id)踢掉连接

TCP 业务(Handler 继承)

namespace app\worker\tcp;

use Workerman\Connection\TcpConnection;
use adminmatrix\worker\Handler;

class Device extends Handler
{
    public function onConnect(TcpConnection $connection): void
    {
        // 设备上线
    }

    public function onMessage(TcpConnection $connection, string $data): void
    {
        // TCP 收到的是原始数据帧,业务层自行拆包
        $connection->send('recv: ' . $data);
    }

    public function onClose(TcpConnection $connection): void
    {
        // 设备离线
    }
}

配置指向业务类:

'tcp' => [
    'enable' => true,
    'workers' => [
        ['name' => '设备接入', 'host' => '0.0.0.0', 'port' => 2349, 'handler' => 'app\worker\tcp\Device'],
    ],
],

目录结构

src/
├── command/Run.php               # think 命令入口(php think workers)
├── config/matrix_worker.php      # 配置模板(主项目无配置时自动注入)
├── HandlerInterface.php          # 公共契约:必须实现的 4 个连接事件 + 可选事件标注
├── Handler.php                   # 公共基类:集成 think console Output(info/error 等日志输出)
├── Service.php                   # think 服务注册(配置注入)
├── Worker.php                    # 启动器 + 服务容器基类(服务列表 / think Table 渲染 / 上下文记录)
├── server/                       # 服务容器
│   ├── Register.php              # GatewayWorker 注册中心
│   ├── Business.php              # GatewayWorker 业务进程
│   ├── Gateway.php               # GatewayWorker 网关(含心跳配置)
│   ├── WebSocket.php             # WebSocket 直连容器(备用)
│   ├── Tcp.php                   # TCP 容器
│   └── Queue.php                 # 队列消费容器
├── websocket/
│   ├── Events.php                # Gateway 默认业务事件类
│   ├── HandlerInterface.php      # WebSocket 契约(+ onWebSocketConnect 握手鉴权)
│   └── Handler.php               # 直连模式默认处理器(备用)
└── tcp/
    ├── HandlerInterface.php      # TCP 契约(原始帧 / 粘包拆包标注)
    └── Handler.php               # TCP 默认处理器

多机部署

  • 所有机器的 register.host 指向同一台 Register 机器
  • 每台机器的 lanIp 填自己的内网 IP
  • 各机器网关 startPort 不重叠(同机多网关会自动按 100 错开)

License

MIT