├── .gitignore ├── LICENSE ├── README.md ├── README_CN.md ├── composer.json ├── config └── gateway-worker.php └── src ├── Commands └── GatewayWorkerCommand.php ├── GatewayWorker ├── GatewayWorkerEvents.php ├── GatewayWorkerService.php └── Push │ └── PushEvent.php └── GatewayWorkerServiceProvider.php /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .project 3 | .settings 4 | .idea 5 | .DS_Store 6 | 7 | vendor 8 | logs 9 | worker 10 | *.pid 11 | *.log 12 | *.cache 13 | composer.lock 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 smileymrking 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [English](./README.md)|[中文](./README_CN.md) 2 | # Laravel GatewayWorker 3 | In order to use [GatewayWorker](https://github.com/walkor/GatewayWorker) more elegantly in Laravel, I developed this extension based on GatewayWorker to make it ready to use. 4 | 5 | ## Installation 6 | ```shell 7 | composer require smileymrking/laravel-gateway-worker 8 | ``` 9 | 10 | ## Configuration 11 | 12 | ### Laravel 13 | 14 | 1. Register the ServiceProvider and Facade in `config/app.php` (For Laravel 5.5 and above, no manual registration is required) 15 | 16 | ```php 17 | 'providers' => [ 18 | // ... 19 | SmileyMrKing\GatewayWorker\GatewayWorkerServiceProvider::class, 20 | ]; 21 | ``` 22 | 23 | 2. Publish the configuration file: 24 | 25 | ```shell 26 | php artisan vendor:publish --provider="SmileyMrKing\GatewayWorker\GatewayWorkerServiceProvider" 27 | ``` 28 | 29 | 3. Modify the corresponding configurations in `config/gateway-worker.php` located in the application root directory. 30 | 31 | ### Lumen 32 | > Lumen has not been used or tested, the following instructions are based on other extension package development. 33 | 34 | 1. In `bootstrap/app.php` around line 82: 35 | 36 | ```php 37 | $app->register(SmileyMrKing\GatewayWorker\GatewayWorkerServiceProvider::class); 38 | ``` 39 | 40 | 2. Publish the `config/gateway-worker.php` configuration file by copying it from `vendor/smileymrking/laravel-gateway-worker/config/gateway-worker.php` to the `project_root/config` directory. 41 | 42 | The configuration file already has a default websocket service named 'push', you can adjust the relevant configurations accordingly, or directly proceed to the next step to start the service. 43 | 44 | ```php 45 | return [ 46 | 47 | /* 48 | |-------------------------------------------------------------------------- 49 | | Gateway Worker Service 50 | |-------------------------------------------------------------------------- 51 | */ 52 | 53 | 'default_service' => 'push', # Set Gateway::$registerAddress to push.register_address by default 54 | 55 | 'push' => [ 56 | 'lan_ip' => env('WS_LAN_IP', '127.0.0.1'), # Internal IP, fill in the real internal IP when deploying in a multi-server distributed environment. 57 | 58 | 'register' => env('WS_REGISTER', 'text://0.0.0.0:20000'), 59 | 'register_address' => env('WS_REGISTER_ADDRESS', '127.0.0.1:20000'), # Registration service address 60 | 61 | 'worker_name' => 'PushBusinessWorker', # Set the name of the BusinessWorker process 62 | 'worker_count' => 1, # Set the number of BusinessWorker processes 63 | # Set which class to handle business logic. The class must implement the static method 'onMessage'. 'onConnect' and 'onClose' static methods are optional. 64 | 'event_handler' => \SmileyMrKing\GatewayWorker\Push\PushEvent::class, 65 | 66 | 'gateway' => env('WS_GATEWAY', 'websocket://0.0.0.0:20010'),# Address allowed for connection 67 | 'gateway_name' => 'PushGateway', # Set the name of the Gateway process for easy statistics in the 'status' command 68 | 'gateway_count' => 1, # Number of Gateway processes 69 | 'start_port' => env('WS_START_PORT', '20100'), # Starting port for listening on the local machine 70 | 'ping_interval' => 55, # Heartbeat interval, only for server-side heartbeat 71 | 'ping_not_response_limit' => 1, # 0: server actively sends heartbeat, 1: client actively sends heartbeat 72 | 'ping_data' => '{"type":"ping"}', # Data for the server to actively send heartbeat, only for server-side heartbeat. When the client times out without sending heartbeat, the server will actively send a heartbeat detection. 73 | 74 | 'gateway_start' => true, 75 | 'business_worker_start' => true, 76 | 'register_start' => true, 77 | 78 | 'gateway_transport' => 'tcp', // When set to 'ssl', SSL will be enabled, websocket+SSL is 'wss' 79 | /*'gateway_context' => [ 80 | // For more SSL options, please refer to the manual: http://php.net/manual/en/context.ssl.php 81 | 'ssl' => array( 82 | // Please use absolute paths 83 | 'local_cert' => '/your/path/of/server.pem', // It can also be a crt file 84 | 'local_pk' => '/your/path/of/server.key', 85 | 'verify_peer' => false, 86 | 'allow_self_signed' => true, // Enable this option if it's a self-signed certificate 87 | ) 88 | ],*/ 89 | ], 90 | 91 | 'pid_file' => null, // Custom PID file absolute path, by default in 'vendor/smileymrking/laravel-gateway-worker/src/GatewayWorker/worker' directory 92 | 'log_file' => null, // Custom log file absolute path, same as above by default 93 | 94 | ]; 95 | 96 | ``` 97 | 98 | ### Starting the service 99 | Use the following command to start the service: 100 | `php artisan gateway-worker {serviceName} {action} {--d}` 101 | 102 | | Parameter | Description | 103 | |:---:|:---| 104 | |serviceName|Service name, which is the key name in the configuration file.| 105 | |action|Action command, available commands are `status`, `start`, `stop`, `restart`, `reload`, `connections`.| 106 | |--d|Use DAEMON mode.| 107 | 108 | ```shell 109 | > php artisan gateway-worker push start 110 | 111 | Workerman[gateway-worker push] start in DEBUG mode 112 | ----------------------------------------------- WORKERMAN ----------------------------------------------- 113 | Workerman version:4.0.6 PHP version:7.2.5-1+ubuntu18.04.1+deb.sury.org+1 114 | ------------------------------------------------ WORKERS ------------------------------------------------ 115 | proto user worker listen processes status 116 | tcp vagrant PushGateway websocket://0.0.0.0:20010 1 [OK] 117 | tcp vagrant PushBusinessWorker none 1 [OK] 118 | tcp vagrant Register text://0.0.0.0:20000 1 [OK] 119 | --------------------------------------------------------------------------------------------------------- 120 | Press Ctrl+C to stop. Start success. 121 | ``` 122 | > 'push' is the default service name that was created, you can synchronize the configuration file and modify the relevant configurations as needed. 123 | 124 | ## Creating Multiple Services 125 | > You can start multiple services simultaneously. 126 | 127 | #### Adding a new service 128 | Directly copy a duplicate of the 'push' configuration file and make the necessary modifications, paying attention to updating the 'worker_name', 'gateway_name', and related port configurations to avoid duplication. The key used in the configuration will be the service name. 129 | 130 | ```php 131 | return [ 132 | // ... 133 | 'demo' => [ 134 | 'lan_ip' => env('WS_LAN_IP_DEMO', '127.0.0.1'), # Internal IP, fill in the real internal IP when deploying in a multi-server distributed environment. 135 | 136 | 'register' => env('WS_REGISTER_DEMO', 'text://0.0.0.0:20000'), 137 | 'register_address' => env('WS_REGISTER_ADDRESS_DEMO', '127.0.0.1:20000'), # Registration service address 138 | 139 | 'worker_name' => 'DemoBusinessWorker', # Set the name of the BusinessWorker process 140 | 'worker_count' => 1, # Set the number of BusinessWorker processes 141 | # Set which class to handle business logic. The class must implement the static method 'onMessage'. 'onConnect' and 'onClose' static methods are optional. 142 | 'event_handler' => \App\GatewayWorker\Demo\DemoEvent::class, 143 | 144 | 'gateway' => env('WS_GATEWAY_DEMO', 'websocket://0.0.0.0:20010'),# Address allowed for connection 145 | 'gateway_name' => 'DemoGateway', # Set the name of the Gateway process for easy statistics in the 'status' command 146 | 'gateway_count' => 1, # Number of Gateway processes 147 | 'start_port' => env('WS_START_PORT_DEMO', '20100'), # Starting port for listening on the local machine 148 | 'ping_interval' => 55, # Heartbeat interval, only for server-side heartbeat 149 | 'ping_not_response_limit' => 1, # 0: server actively sends heartbeat, 1: client actively sends heartbeat 150 | 'ping_data' => '{"type":"ping"}', # Data for the server to actively send heartbeat, only for server-side heartbeat. When the client times out without sending heartbeat, the server will actively send a heartbeat detection. 151 | 152 | 'gateway_start' => true, 153 | 'business_worker_start' => true, 154 | 'register_start' => true, 155 | 156 | 'gateway_transport' => 'tcp', // When set to 'ssl', SSL will be enabled, websocket+SSL is 'wss' 157 | /*'gateway_context' => [ 158 | // For more SSL options, please refer to the manual: http://php.net/manual/en/context.ssl.php 159 | 'ssl' => array( 160 | // Please use absolute paths 161 | 'local_cert' => '/your/path/of/server.pem', // It can also be a crt file 162 | 'local_pk' => '/your/path/of/server.key', 163 | 'verify_peer' => false, 164 | 'allow_self_signed' => true, // Enable this option if it's a self-signed certificate 165 | ) 166 | ],*/ 167 | 'pid_file' => storage_path('logs/gateway-worker-demo.pid'), 168 | 'log_file' => storage_path('logs/gateway-worker-demo.log'), 169 | ], 170 | 171 | ]; 172 | 173 | ``` 174 | 175 | 176 | After completing the configuration modifications, use the `php artisan gateway-worker demo start` command to start the service, where 'demo' is the key name you configured. 177 | 178 | #### Custom Event Handler 179 | When 'event_handler' is not configured, it will use the `SmileyMrKing\GatewayWorker\GatewayWorker\GatewayWorkerEvents` class, which implements the static methods 'onMessage', 'onConnect', and 'onClose'. You can customize the 'event_handler' class by inheriting from `SmileyMrKing\GatewayWorker\GatewayWorker\GatewayWorkerEvents` and overriding the relevant static methods. 180 | 181 | ```php 182 | namespace App\GatewayWorker\Demo; 183 | 184 | use SmileyMrKing\GatewayWorker\GatewayWorker\GatewayWorkerEvents; 185 | 186 | class DemoEvent extends GatewayWorkerEvents 187 | { 188 | public static function onMessage($client_id, $message) 189 | { 190 | // Do something 191 | } 192 | } 193 | ``` 194 | 195 | The 'default_service' configuration specifies which service's registration address Gateway::$registerAddress will connect to by default. 196 | 197 | ## Message Pushing 198 | You can directly use the `\GatewayWorker\Lib\Gateway` class in GatewayWorker. For specific usage, please refer to the [GatewayWorker manual](http://doc2.workerman.net/). 199 | 200 | ## Viewing Logs 201 | The logs and PID files are located in the `vendor/smileymrking/laravel-gateway-worker/src/GatewayWorker/worker` directory. You can customize the log and PID paths using the `pid_file` and `log_file` settings in the configuration. 202 | 203 | ## References 204 | - [GatewayWorker 2.x 3.x Manual](http://doc2.workerman.net/) 205 | - [Using Laravel to Carry Out Socket Communication in Workerman](https://learnku.com/articles/13151/using-laravel-to-carry-out-socket-communication-in-workerman) 206 | 207 | ## License 208 | 209 | MIT 210 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | > [English](./README.md)|[中文](./README_CN.md) 2 | # Laravel GatewayWorker 3 | 为了能够在 Laravel 中更优雅的使用 [GatewayWorker](https://github.com/walkor/GatewayWorker) 于是我基于 GatewayWorker 开发了这个扩展,使其能够开箱即用。 4 | 5 | ## 安装 6 | ```shell 7 | composer require smileymrking/laravel-gateway-worker 8 | ``` 9 | 10 | ## 配置 11 | 12 | ### Laravel 13 | 14 | 1. 在 `config/app.php` 注册 ServiceProvider 和 Facade (Laravel 5.5 + 无需手动注册) 15 | 16 | ```php 17 | 'providers' => [ 18 | // ... 19 | SmileyMrKing\GatewayWorker\GatewayWorkerServiceProvider::class, 20 | ]; 21 | ``` 22 | 23 | 2. 创建配置文件: 24 | 25 | ```shell 26 | php artisan vendor:publish --provider="SmileyMrKing\GatewayWorker\GatewayWorkerServiceProvider" 27 | ``` 28 | 29 | 3. 修改应用根目录下的 `config/gateway-worker.php` 中对应的配置即可。 30 | 31 | ### Lumen 32 | > 并未使用过 Lumen 未实际测试,以下参考其他扩展包编写 33 | 34 | 1. 在 `bootstrap/app.php` 中 82 行左右: 35 | 36 | ```php 37 | $app->register(SmileyMrKing\GatewayWorker\GatewayWorkerServiceProvider::class); 38 | ``` 39 | 40 | 2. 发布 `config/gateway-worker.php` 配置文件,将 `vendor/smileymrking/laravel-gateway-worker/config/gateway-worker.php` 拷贝到`项目根目录/config`目录下。 41 | 42 | 43 | 配置文件中已默认创建了一个名为 push 的 websocket 服务,配置如下,可自行调整相关配置,或无需发布配置文件,直接进入下一步启动服务 44 | ```php 45 | return [ 46 | 47 | /* 48 | |-------------------------------------------------------------------------- 49 | | Gateway Worker Service 50 | |-------------------------------------------------------------------------- 51 | */ 52 | 53 | 'default_service' => 'push', # 默认的 Gateway::$registerAddress 设置为 push.register_address 54 | 55 | 'push' => [ 56 | 'lan_ip' => env('WS_LAN_IP', '127.0.0.1'), #内网ip,多服务器分布式部署的时候需要填写真实的内网ip 57 | 58 | 'register' => env('WS_REGISTER', 'text://0.0.0.0:20000'), 59 | 'register_address' => env('WS_REGISTER_ADDRESS', '127.0.0.1:20000'), #注册服务地址 60 | 61 | 'worker_name' => 'PushBusinessWorker', #设置 BusinessWorker 进程的名称 62 | 'worker_count' => 1, #设置 BusinessWorker 进程的数量 63 | # 设置使用哪个类来处理业务,业务类至少要实现onMessage静态方法,onConnect 和 onClose 静态方法可以不用实现 64 | 'event_handler' => \SmileyMrKing\GatewayWorker\Push\PushEvent::class, 65 | 66 | 'gateway' => env('WS_GATEWAY', 'websocket://0.0.0.0:20010'),# 允许连接服务的地址 67 | 'gateway_name' => 'PushGateway', #设置 Gateway 进程的名称,方便status命令中查看统计 68 | 'gateway_count' => 1, # Gateway 进程的数量 69 | 'start_port' => env('WS_START_PORT', '20100'), #监听本机端口的起始端口 70 | 'ping_interval' => 55, # 心跳间隔时间,只针对服务端发送心跳 71 | 'ping_not_response_limit' => 1, # 0 服务端主动发送心跳, 1 客户端主动发送心跳 72 | 'ping_data' => '{"type":"ping"}', # 服务端主动发送心跳的数据,只针对服务端发送心跳,客户端超时未发送心跳时会主动向客户端发送一次心跳检测 73 | 74 | 'gateway_start' => true, 75 | 'business_worker_start' => true, 76 | 'register_start' => true, 77 | 78 | 'gateway_transport' => 'tcp', // 当为 ssl 时,开启SSL,websocket+SSL 即 wss 79 | /*'gateway_context' => [ 80 | // 更多ssl选项请参考手册 http://php.net/manual/zh/context.ssl.php 81 | 'ssl' => array( 82 | // 请使用绝对路径 83 | 'local_cert' => '/your/path/of/server.pem', // 也可以是crt文件 84 | 'local_pk' => '/your/path/of/server.key', 85 | 'verify_peer' => false, 86 | 'allow_self_signed' => true, //如果是自签名证书需要开启此选项 87 | ) 88 | ],*/ 89 | ], 90 | 91 | 'pid_file' => null, // 自定义pid文件绝对路径,默认在vendor/smileymrking/laravel-gateway-worker/src/GatewayWorker/worker目录下 92 | 'log_file' => null, // 自定义日志文件绝对路径,默认同上 93 | 94 | ]; 95 | 96 | ``` 97 | 98 | ### 启动服务 99 | 使用以下命令启动服务 100 | `php artisan gateway-worker {serviceName} {action} {--d}` 101 | 102 | |参数|释义| 103 | |:---:|:---| 104 | |serviceName|服务名称,即配置文件中的键名| 105 | |action|操作命令,可用命令有 `status` 、 `start` 、 `stop` 、 `restart` 、 `reload` 、 `connections`| 106 | |--d|使用 DAEMON 模式| 107 | 108 | ```shell 109 | > php artisan gateway-worker push start 110 | 111 | Workerman[gateway-worker push] start in DEBUG mode 112 | ----------------------------------------------- WORKERMAN ----------------------------------------------- 113 | Workerman version:4.0.6 PHP version:7.2.5-1+ubuntu18.04.1+deb.sury.org+1 114 | ------------------------------------------------ WORKERS ------------------------------------------------ 115 | proto user worker listen processes status 116 | tcp vagrant PushGateway websocket://0.0.0.0:20010 1 [OK] 117 | tcp vagrant PushBusinessWorker none 1 [OK] 118 | tcp vagrant Register text://0.0.0.0:20000 1 [OK] 119 | --------------------------------------------------------------------------------------------------------- 120 | Press Ctrl+C to stop. Start success. 121 | ``` 122 | > `push` 为默认创建的服务名称,可同步发布配置文件,自行修改相关配置 123 | 124 | ## 创建多个服务 125 | > 可同时启动多个服务 126 | 127 | #### 新增服务 128 | 直接复制一份 push 的配置文件进行修改,注意需要修改 `worker_name` 、`gateway_name` 和相关端口的配置,避免重复,配置的key即为服务名称 129 | 130 | ```php 131 | return [ 132 | // ... 133 | 'demo' => [ 134 | 'lan_ip' => env('WS_LAN_IP_DEMO', '127.0.0.1'), #内网ip,多服务器分布式部署的时候需要填写真实的内网ip 135 | 136 | 'register' => env('WS_REGISTER_DEMO', 'text://0.0.0.0:20000'), 137 | 'register_address' => env('WS_REGISTER_ADDRESS_DEMO', '127.0.0.1:20000'), #注册服务地址 138 | 139 | 'worker_name' => 'DemoBusinessWorker', #设置 BusinessWorker 进程的名称 140 | 'worker_count' => 1, #设置 BusinessWorker 进程的数量 141 | # 设置使用哪个类来处理业务,业务类至少要实现onMessage静态方法,onConnect 和 onClose 静态方法可以不用实现 142 | 'event_handler' => \App\GatewayWorker\Demo\DemoEvent::class, 143 | 144 | 'gateway' => env('WS_GATEWAY_DEMO', 'websocket://0.0.0.0:20010'),# 允许连接服务的地址 145 | 'gateway_name' => 'DemoGateway', #设置 Gateway 进程的名称,方便status命令中查看统计 146 | 'gateway_count' => 1, # Gateway 进程的数量 147 | 'start_port' => env('WS_START_PORT_DEMO', '20100'), #监听本机端口的起始端口 148 | 'ping_interval' => 55, # 心跳间隔时间,只针对服务端发送心跳 149 | 'ping_not_response_limit' => 1, # 0 服务端主动发送心跳, 1 客户端主动发送心跳 150 | 'ping_data' => '{"type":"ping"}', # 服务端主动发送心跳的数据,只针对服务端发送心跳,客户端超时未发送心跳时会主动向客户端发送一次心跳检测 151 | 152 | 'gateway_start' => true, 153 | 'business_worker_start' => true, 154 | 'register_start' => true, 155 | 156 | 'gateway_transport' => 'tcp', // 当为 ssl 时,开启SSL,websocket+SSL 即 wss 157 | /*'gateway_context' => [ 158 | // 更多ssl选项请参考手册 http://php.net/manual/zh/context.ssl.php 159 | 'ssl' => array( 160 | // 请使用绝对路径 161 | 'local_cert' => '/your/path/of/server.pem', // 也可以是crt文件 162 | 'local_pk' => '/your/path/of/server.key', 163 | 'verify_peer' => false, 164 | 'allow_self_signed' => true, //如果是自签名证书需要开启此选项 165 | ) 166 | ],*/ 167 | 'pid_file' => storage_path('logs/demo-gateway-worker.pid'), 168 | 'log_file' => storage_path('logs/demo-gateway-worker.log'), 169 | ], 170 | 171 | ]; 172 | 173 | ``` 174 | 175 | 176 | 配置修改完成后使用 `php artisan gateway-worker demo start` 命令启动,`demo` 为刚刚配置的键名 177 | 178 | #### 自定义Event Handler 179 | `event_handler` 未配置时默认使用 `SmileyMrKing\GatewayWorker\GatewayWorker\GatewayWorkerEvents` ,实现了 `onMessage` 、`onConnect`、`onClose` 三个静态方法 180 | 可自定义 `event_handler` 类,需要继承 `SmileyMrKing\GatewayWorker\GatewayWorker\GatewayWorkerEvents` 然后重写相关静态方法 181 | ```php 182 | namespace App\GatewayWorker\Demo; 183 | 184 | use SmileyMrKing\GatewayWorker\GatewayWorker\GatewayWorkerEvents; 185 | 186 | class DemoEvent extends GatewayWorkerEvents 187 | { 188 | public static function onMessage($client_id, $message) 189 | { 190 | // Do something 191 | } 192 | } 193 | ``` 194 | 195 | `default_service` 配置是指定 Gateway::$registerAddress 默认连接的哪个服务的注册地址 `register_address` 196 | 197 | ## 消息推送 198 | 可直接使用 GatewayWorker 中的 `\GatewayWorker\Lib\Gateway` 类,具体用法请查看 [GatewayWorker 手册](http://doc2.workerman.net/) 199 | 200 | ## 日志查看 201 | 日志和PID文件位于 `vendor/smileymrking/laravel-gateway-worker/src/GatewayWorker/worker` 目录下 202 | 可通过配置中的 `pid_file` 和 `log_file` 自定义日志和PID路径 203 | 204 | ## 参考 205 | - [GatewayWorker2.x 3.x 手册](http://doc2.workerman.net/) 206 | - [在 Laravel 中使用 Workerman 进行 socket 通讯](https://learnku.com/articles/13151/using-laravel-to-carry-out-socket-communication-in-workerman) 207 | 208 | ## License 209 | 210 | MIT 211 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smileymrking/laravel-gateway-worker", 3 | "description": "GatewayWorker SDK for Laravel", 4 | "keywords": ["gatewayworker", "workerman","laravel", "sdk"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "smileymrking", 9 | "email": "smileymrking@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "illuminate/console": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.18|^7.0|^8.0|^9.0|^10.0", 14 | "illuminate/support": "~5.5.0|~5.6.0|~5.7.0|~5.8.0|^6.18|^7.0|^8.0|^9.0|^10.0", 15 | "workerman/gateway-worker": "^3.0", 16 | "ext-json": "*" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "SmileyMrKing\\GatewayWorker\\": "src/" 21 | } 22 | }, 23 | "extra": { 24 | "laravel": { 25 | "providers": [ 26 | "SmileyMrKing\\GatewayWorker\\GatewayWorkerServiceProvider" 27 | ] 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /config/gateway-worker.php: -------------------------------------------------------------------------------- 1 | 'push', # 默认的 Gateway::$registerAddress 设置为 push.register_address 18 | 19 | 'push' => [ 20 | 'lan_ip' => env('WS_LAN_IP', '127.0.0.1'), #内网ip,多服务器分布式部署的时候需要填写真实的内网ip 21 | 22 | 'register' => env('WS_REGISTER', 'text://0.0.0.0:20000'), 23 | 'register_address' => env('WS_REGISTER_ADDRESS', '127.0.0.1:20000'), #注册服务地址 24 | 25 | 'worker_name' => 'PushBusinessWorker', #设置 BusinessWorker 进程的名称 26 | 'worker_count' => 1, #设置 BusinessWorker 进程的数量 27 | # 设置使用哪个类来处理业务,业务类至少要实现onMessage静态方法,onConnect 和 onClose 静态方法可以不用实现 28 | 'event_handler' => \SmileyMrKing\GatewayWorker\GatewayWorker\Push\PushEvent::class, 29 | 30 | 'gateway' => env('WS_GATEWAY', 'websocket://0.0.0.0:20010'),# 允许连接服务的地址 31 | 'gateway_name' => 'PushGateway', #设置 Gateway 进程的名称,方便status命令中查看统计 32 | 'gateway_count' => 1, # Gateway 进程的数量 33 | 'start_port' => env('WS_START_PORT', '20100'), #监听本机端口的起始端口 34 | 'ping_interval' => 55, # 心跳间隔时间,只针对服务端发送心跳 35 | 'ping_not_response_limit' => 1, # 0 服务端主动发送心跳, 1 客户端主动发送心跳 36 | 'ping_data' => '{"type":"ping"}', # 服务端主动发送心跳的数据,只针对服务端发送心跳,客户端超时未发送心跳时会主动向客户端发送一次心跳检测 37 | 38 | 'gateway_start' => true, 39 | 'business_worker_start' => true, 40 | 'register_start' => true, 41 | 42 | 'gateway_transport' => 'tcp', // 当为 ssl 时,开启SSL,websocket+SSL 即 wss 43 | /*'gateway_context' => [ 44 | // 更多ssl选项请参考手册 http://php.net/manual/zh/context.ssl.php 45 | 'ssl' => array( 46 | // 请使用绝对路径 47 | 'local_cert' => '/your/path/of/server.pem', // 也可以是crt文件 48 | 'local_pk' => '/your/path/of/server.key', 49 | 'verify_peer' => false, 50 | 'allow_self_signed' => true, //如果是自签名证书需要开启此选项 51 | ) 52 | ],*/ 53 | 54 | 'pid_file' => null, // 自定义pid文件绝对路径,默认在vendor/smileymrking/laravel-gateway-worker/src/GatewayWorker/worker目录下 55 | 'log_file' => null, // 自定义日志文件绝对路径,默认同上 56 | ], 57 | 58 | ]; 59 | -------------------------------------------------------------------------------- /src/Commands/GatewayWorkerCommand.php: -------------------------------------------------------------------------------- 1 | argument('action'), ['status', 'start', 'stop', 'restart', 'reload', 'connections'])) { 44 | $this->error('Invalid Arguments'); 45 | return; 46 | } 47 | $serviceName = $this->argument('serviceName'); 48 | $daemon = $this->option('d') ? '-d' : ''; 49 | $argv[0] = 'gateway-worker ' . $serviceName; 50 | $argv[1] = $action; 51 | $argv[2] = $daemon; 52 | try { 53 | GatewayWorkerService::startAll($serviceName); 54 | } catch (\Exception $e) { 55 | $this->error($e->getMessage()); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/GatewayWorker/GatewayWorkerEvents.php: -------------------------------------------------------------------------------- 1 | 'connect', 30 | 'client_id' => $client_id 31 | ]; 32 | // 向当前client_id发送数据 33 | Gateway::sendToClient($client_id, json_encode($data)); 34 | } 35 | 36 | /** 37 | * 当客户端发来消息时触发 38 | * @param int $client_id 连接id 39 | * @param mixed $message 具体消息 40 | * @throws \Exception 41 | */ 42 | public static function onMessage($client_id, $message) 43 | { 44 | } 45 | 46 | /** 47 | * 当用户断开连接时触发 48 | * @param int $client_id 连接id 49 | * @throws \Exception 50 | */ 51 | public static function onClose($client_id) 52 | { 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/GatewayWorker/GatewayWorkerService.php: -------------------------------------------------------------------------------- 1 | name = $this->config('worker_name'); #设置BusinessWorker进程的名称 20 | $worker->count = $this->config('worker_count'); #设置BusinessWorker进程的数量 21 | $worker->registerAddress = $this->config('register_address'); #注册服务地址 22 | // 设置使用哪个类来处理业务,业务类至少要实现onMessage静态方法,onConnect和onClose静态方法可以不用实现 23 | $worker->eventHandler = $this->config('event_handler', GatewayWorkerEvents::class); 24 | } 25 | 26 | public function startGateWay() 27 | { 28 | $gateway = new Gateway($this->config('gateway'), $this->config('gateway_context', [])); #连接服务的端口 29 | $gateway->transport = $this->config('gateway_transport', 'tcp'); 30 | $gateway->name = $this->config('gateway_name'); #设置Gateway进程的名称,方便status命令中查看统计 31 | $gateway->count = $this->config('gateway_count'); #进程的数量 32 | $gateway->lanIp = $this->config('lan_ip'); #内网ip,多服务器分布式部署的时候需要填写真实的内网ip 33 | $gateway->startPort = $this->config('start_port'); #监听本机端口的起始端口 34 | $gateway->pingInterval = $this->config('ping_interval'); 35 | $gateway->pingNotResponseLimit = $this->config('ping_not_response_limit'); # 0 服务端主动发送心跳, 1 客户端主动发送心跳 36 | $gateway->pingData = $this->config('ping_data'); # 服务端主动发送心跳的数据 37 | $gateway->registerAddress = $this->config('register_address'); #注册服务地址 38 | } 39 | 40 | public function startRegister() 41 | { 42 | new Register($this->config('register')); # 允许注册通讯的地址 43 | } 44 | 45 | public function ready($serviceName) 46 | { 47 | $this->serviceName = $serviceName; 48 | if ($this->config('gateway_start')) $this->startGateWay(); 49 | if ($this->config('business_worker_start')) $this->startBusinessWorker(); 50 | if ($this->config('register_start')) $this->startRegister(); 51 | 52 | $path = __DIR__ . '/worker'; 53 | if (!is_dir($path)) mkdir($path); 54 | $unique_prefix = "gateway-worker-" . \str_replace('\\', '_', $serviceName); 55 | 56 | $pidFile = $this->config('pid_file') ?: "$path/$unique_prefix.pid"; 57 | $logFile = $this->config('log_file') ?: "$path/$unique_prefix.log"; 58 | 59 | Worker::$pidFile = $pidFile; 60 | Worker::$logFile = $logFile; 61 | } 62 | 63 | public static function startAll($serviceName) 64 | { 65 | (new static())->ready($serviceName); 66 | Worker::runAll(); 67 | } 68 | 69 | protected function config($name, $default = null) 70 | { 71 | $this->configs = $this->getConfigs(); 72 | if (empty($this->configs[$name])) { 73 | return $default; 74 | } 75 | return $this->configs[$name]; 76 | } 77 | 78 | /** 79 | * @throws Exception 80 | */ 81 | protected function getConfigs() 82 | { 83 | if (!empty($this->configs)) { 84 | return $this->configs; 85 | } 86 | $this->configs = config("gateway-worker.{$this->serviceName}"); 87 | if (empty($this->configs)) { 88 | throw new Exception("{$this->serviceName}'s GatewayWorker config doesn't exist"); 89 | } 90 | return $this->configs; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/GatewayWorker/Push/PushEvent.php: -------------------------------------------------------------------------------- 1 | 'close'])); 23 | } 24 | } 25 | 26 | public static function sendToAll($client_id, $message) { 27 | Gateway::sendToAll($message["msg"]); 28 | } 29 | 30 | public static function sendToClient($client_id, $message) { 31 | Gateway::sendToClient($client_id, $message["msg"]); 32 | } 33 | 34 | public static function sendToUid($client_id, $message) { 35 | Gateway::sendToUid($message["uid"], $message["msg"]); 36 | } 37 | 38 | public static function sendToCurrentClient($client_id, $message) { 39 | Gateway::sendToCurrentClient($message["msg"]); 40 | } 41 | 42 | public static function sendToGroup($client_id, $message) { 43 | Gateway::sendToGroup($message["group"], $message["msg"]); 44 | } 45 | 46 | public static function bindUid($client_id, $message) { 47 | Gateway::bindUid($client_id, $message["uid"]); 48 | } 49 | 50 | public static function closeClient($client_id, $message) { 51 | Gateway::closeClient($client_id); 52 | } 53 | 54 | /** 55 | * @throws \Exception 56 | */ 57 | public static function closeCurrentClient($client_id, $message) { 58 | Gateway::closeCurrentClient($message["msg"]); 59 | } 60 | 61 | public static function destoryClient($client_id, $message) { 62 | Gateway::destoryClient($client_id); 63 | } 64 | 65 | public static function destoryCurrentClient($client_id, $message) { 66 | Gateway::destoryCurrentClient(); 67 | } 68 | 69 | public static function joinGroup($client_id, $message) { 70 | Gateway::joinGroup($client_id, $message["group"]); 71 | } 72 | 73 | public static function leaveGroup($client_id, $message) { 74 | Gateway::leaveGroup($client_id, $message["group"]); 75 | } 76 | 77 | public static function getAllClientIdCount($client_id, $message) { 78 | return Gateway::getAllClientIdCount(); 79 | } 80 | 81 | public static function getAllClientCount($client_id, $message) { 82 | return Gateway::getAllClientCount(); 83 | } 84 | 85 | public static function getAllGroupClientIdCount($client_id, $message) { 86 | return Gateway::getAllGroupClientIdCount(); 87 | } 88 | 89 | public static function getAllClientIdList($client_id, $message) { 90 | return Gateway::getAllClientIdList(); 91 | } 92 | 93 | public static function getAllClientInfo($client_id, $message) { 94 | return Gateway::getAllClientInfo($message["group"]); 95 | } 96 | 97 | public static function getAllGroupClientIdList($client_id, $message) { 98 | return Gateway::getAllGroupClientIdList(); 99 | } 100 | 101 | public static function getAllGroupUidList($client_id, $message) { 102 | return Gateway::getAllGroupUidList(); 103 | } 104 | 105 | public static function getAllUidList($client_id, $message) { 106 | return Gateway::getAllUidList(); 107 | } 108 | 109 | public static function getAllUidCount($client_id, $message) { 110 | return Gateway::getAllUidCount(); 111 | } 112 | 113 | public static function getUidListByGroup($client_id, $message) { 114 | return Gateway::getUidListByGroup($message["group"]); 115 | } 116 | 117 | public static function getUidCountByGroup($client_id, $message) { 118 | return Gateway::getUidCountByGroup($message["group"]); 119 | } 120 | 121 | public static function getSession($client_id, $message) { 122 | return Gateway::getSession($client_id); 123 | } 124 | 125 | public static function getAllClientSessions($client_id, $message) { 126 | return Gateway::getAllClientSessions($message["group"]); 127 | } 128 | 129 | public static function getClientInfoByGroup($client_id, $message) { 130 | return Gateway::getClientInfoByGroup($message["group"]); 131 | } 132 | 133 | public static function getClientIdByUid($client_id, $message) { 134 | return Gateway::getClientIdByUid($message["uid"]); 135 | } 136 | 137 | public static function getAllGroupIdList($client_id, $message) { 138 | return Gateway::getAllGroupIdList(); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/GatewayWorkerServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 14 | __DIR__.'/../config/gateway-worker.php' => config_path('gateway-worker.php'), 15 | ], 'config'); 16 | } 17 | 18 | public function register() 19 | { 20 | $this->mergeConfigFrom(__DIR__.'/../config/gateway-worker.php', 'gateway-worker'); 21 | 22 | $this->app->bind('command.gateway-worker', GatewayWorkerCommand::class); 23 | 24 | $this->commands([ 25 | 'command.gateway-worker', 26 | ]); 27 | 28 | // WebSocket 注册地址 29 | $defaultService = config('gateway-worker.default_service'); 30 | Gateway::$registerAddress = config("gateway-worker.{$defaultService}.register_address"); 31 | } 32 | } 33 | --------------------------------------------------------------------------------