尧图精选

ThinkPHP8整合Workerman实现高性能WebSocket服务

🕒 发布时间:2026/9/17 17:57:30 📁 来源:尧图网络
1. 项目概述最近在重构一个需要实时通信功能的项目时我选择了ThinkPHP8作为基础框架同时整合Workerman来实现高性能的WebSocket服务。这种组合在实际项目中非常实用既能利用ThinkPHP成熟的MVC架构又能通过Workerman突破传统PHP在长连接应用中的性能瓶颈。ThinkPHP8作为国内最流行的PHP框架之一提供了优雅的代码结构和丰富的功能组件。而Workerman则是一个纯PHP开发的高性能Socket服务器框架特别适合开发实时应用。将两者结合使用可以充分发挥各自的优势构建出既便于业务开发又具备高并发能力的应用系统。2. 环境准备与基础配置2.1 环境要求检查在开始整合前我们需要确保开发环境满足以下要求PHP版本≥7.3Workerman需要PHP7.0ThinkPHP8要求PHP7.1已安装Composer依赖管理工具服务器需要开启socket扩展通常默认已安装建议使用Linux环境Windows下Workerman性能会打折扣可以通过以下命令快速检查环境php -v composer -v php -m | grep sockets2.2 创建ThinkPHP8项目使用Composer创建一个新的ThinkPHP8项目composer create-project topthink/think tp8-workerman-demo cd tp8-workerman-demo安装完成后建议先测试基础框架是否正常运行php think run访问http://localhost:8000应该能看到ThinkPHP的欢迎页面。2.3 安装Workerman在项目根目录下通过Composer安装Workermancomposer require workerman/workerman为了后续开发方便我们还可以安装WebSocket支持composer require workerman/phpsocket.io3. Workerman服务整合3.1 创建基础服务文件在项目根目录创建server目录然后新建websocket.php文件?php namespace server; use Workerman\Worker; use Workerman\Connection\TcpConnection; require_once __DIR__ . /../vendor/autoload.php; // 创建一个Worker监听2345端口使用websocket协议通讯 $ws_worker new Worker(websocket://0.0.0.0:2345); // 启动4个进程对外提供服务 $ws_worker-count 4; // 当有客户端连接时 $ws_worker-onConnect function(TcpConnection $connection) { echo New connection\n; }; // 当客户端发来消息时 $ws_worker-onMessage function(TcpConnection $connection, $data) { $connection-send(Hello . $data); }; // 当客户端断开连接时 $ws_worker-onClose function(TcpConnection $connection) { echo Connection closed\n; }; // 运行worker Worker::runAll();3.2 与ThinkPHP8的整合策略为了使Workerman服务能够使用ThinkPHP的配置和功能我们需要做以下调整修改websocket.php的自动加载部分// 替换原来的autoload引入 require_once __DIR__ . /../vendor/autoload.php; require_once __DIR__ . /../thinkphp/base.php;在消息处理中集成ThinkPHP的功能$ws_worker-onMessage function(TcpConnection $connection, $data) { // 初始化ThinkPHP应用 $http (new \think\App())-http; $http-run(); // 使用ThinkPHP的日志功能 \think\facade\Log::info(WebSocket message: .$data); // 业务处理 $response Hello . $data; $connection-send($response); };3.3 服务启动与管理为了方便管理我们可以创建一个自定义命令来启动Workerman服务。在app/command目录下创建WebSocket.php?php namespace app\command; use think\console\Command; use think\console\Input; use think\console\Output; use Workerman\Worker; class WebSocket extends Command { protected function configure() { $this-setName(websocket:start) -setDescription(Start WebSocket server); } protected function execute(Input $input, Output $output) { // 创建一个Worker监听2345端口 $ws_worker new Worker(websocket://0.0.0.0:2345); $ws_worker-count 4; // ... 其他回调函数设置 Worker::runAll(); } }然后在config/console.php中注册这个命令return [ commands [ websocket:start app\command\WebSocket, ], ];现在可以通过以下命令启动服务php think websocket:start4. 高级功能实现4.1 用户认证与会话管理在实时应用中用户认证是一个关键问题。我们可以通过以下方式实现在连接建立时进行Token验证$ws_worker-onConnect function(TcpConnection $connection) { // 获取连接参数中的token $token $_GET[token] ?? ; try { // 使用ThinkPHP的JWT组件验证token $jwt \think\facade\Jwt::decode($token); $connection-user_id $jwt-user_id; // 将连接与用户ID关联存储 \app\common\ConnectionMap::add($jwt-user_id, $connection); } catch (\Exception $e) { $connection-close(Authentication failed); } };创建app/common/ConnectionMap.php来管理连接namespace app\common; use Workerman\Connection\TcpConnection; class ConnectionMap { protected static $connections []; public static function add($userId, TcpConnection $connection) { self::$connections[$userId] $connection; } public static function get($userId) { return self::$connections[$userId] ?? null; } public static function remove($userId) { unset(self::$connections[$userId]); } }4.2 消息广播与房间管理实现聊天室功能需要房间管理能力// 在server/websocket.php中添加 $ws_worker-onMessage function(TcpConnection $connection, $data) { $data json_decode($data, true); switch ($data[type]) { case join_room: $connection-room $data[room]; $connection-send(json_encode([ type system, message Joined room: .$data[room] ])); break; case chat_message: // 广播给同房间的所有连接 foreach ($ws_worker-connections as $client) { if ($client-room $connection-room) { $client-send(json_encode([ type chat, user $connection-user_id, message $data[message] ])); } } break; } };4.3 与HTTP接口的交互有时我们需要从HTTP接口触发WebSocket消息推送// 在控制器中 public function notifyUser($userId, $message) { $connection \app\common\ConnectionMap::get($userId); if ($connection) { $connection-send(json_encode([ type notification, message $message ])); return true; } return false; }5. 性能优化与生产部署5.1 进程模型优化Workerman支持多种进程模型对于不同场景可以灵活配置$ws_worker new Worker(websocket://0.0.0.0:2345); // 根据服务器CPU核心数设置进程数 $ws_worker-count swoole_cpu_num() * 2; // 使用多端口监听提高并发能力 $ws_worker-reusePort true;5.2 心跳检测与断线重连保持连接稳定的关键配置// 心跳间隔25秒 $ws_worker-pingInterval 25; // 客户端60秒内没响应则断开 $ws_worker-pingNotResponseLimit 3; $ws_worker-onWebSocketConnect function($connection) { // 设置心跳定时器 $connection-timer_id Timer::add(25, function() use ($connection) { $connection-send(json_encode([type ping])); }); }; $ws_worker-onClose function($connection) { // 清除定时器 Timer::del($connection-timer_id); };5.3 生产环境部署建议使用Supervisor管理进程[program:websocket] command/usr/bin/php /path/to/project/think websocket:start directory/path/to/project userwww autostarttrue autorestarttrue stderr_logfile/var/log/websocket.err.log stdout_logfile/var/log/websocket.out.logNginx反向代理配置server { listen 80; server_name yourdomain.com; location /ws { proxy_pass http://127.0.0.1:2345; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header X-Real-IP $remote_addr; } }6. 常见问题与解决方案6.1 连接数限制问题Workerman默认的连接数限制是1024可以通过以下方式调整// 修改全局连接数限制 Worker::$maxConnections 10000; // 或者在创建worker时指定 $ws_worker new Worker(websocket://0.0.0.0:2345); $ws_worker-maxConnections 10000;6.2 内存泄漏排查长时间运行后可能出现内存增长问题可以通过以下方式排查安装调试组件composer require workerman/workerman-psr7添加内存监控// 每10秒输出一次内存使用情况 Timer::add(10, function() { echo Memory usage: . round(memory_get_usage()/1024/1024, 2) . MB\n; });6.3 跨域问题处理如果前端与WebSocket服务不在同一域名下需要处理跨域问题$ws_worker-onWebSocketConnect function($connection, $http_header) { // 允许所有来源生产环境应限制为特定域名 $connection-header HTTP/1.1 101 WebSocket Protocol Handshake\r\n; $connection-header . Upgrade: websocket\r\n; $connection-header . Connection: Upgrade\r\n; $connection-header . Sec-WebSocket-Accept: . base64_encode(sha1($http_header[Sec-WebSocket-Key] . 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, true)) . \r\n; $connection-header . Access-Control-Allow-Origin: *\r\n\r\n; };7. 实战案例在线客服系统7.1 系统架构设计基于ThinkPHP8和Workerman的在线客服系统架构Web管理端使用ThinkPHP开发处理业务逻辑和数据存储WebSocket服务处理实时消息推送和在线状态管理前端使用Vue.js WebSocket实现实时交互7.2 核心功能实现客服分组与分配// 客服分组管理 class CustomerServiceGroup { protected static $groups []; public static function assign($userId, $groupId) { self::$groups[$groupId][] $userId; } public static function getAvailableAgent($groupId) { foreach (self::$groups[$groupId] ?? [] as $userId) { if ($connection ConnectionMap::get($userId)) { return $userId; } } return null; } }消息持久化与同步// 消息处理中间件 class MessageMiddleware { public static function saveMessage($from, $to, $content) { $message new \app\model\Message(); $message-save([ from_user $from, to_user $to, content $content, create_time time() ]); // 推送给接收方 if ($connection ConnectionMap::get($to)) { $connection-send(json_encode([ type message, from $from, content $content, time date(Y-m-d H:i:s) ])); } } }7.3 性能测试数据在4核8G的服务器上测试结果连接数支持约8000个并发连接消息延迟平均50ms内存占用约300MB8000空闲连接CPU使用率约15%消息频率100条/秒
上一篇/下一篇内容由系统自动关联 返回资讯列表 →