宝塔面板实战:从零部署Workerman WebSocket服务,打通FastAdmin后台与UniApp用户端
1. 环境准备与基础配置在开始部署WebSocket服务之前我们需要确保服务器环境已经准备就绪。宝塔面板作为一款强大的服务器管理工具能够极大简化我们的配置流程。首先登录宝塔面板进入软件商店安装以下必备组件PHP 7.4Workerman对PHP版本有要求建议选择7.4版本Nginx/Apache根据项目需求选择Web服务器MySQL如果FastAdmin需要使用数据库Supervisor用于守护进程管理可选但推荐安装完成后我们需要检查PHP扩展是否完整。进入宝塔的PHP管理界面确保以下扩展已经安装pcntl进程控制posix系统调用sockets套接字支持如果发现缺少扩展直接在宝塔面板中点击安装即可。我曾经遇到过pcntl扩展缺失导致Workerman无法启动的情况所以这一步检查非常重要。2. 创建WebSocket服务项目在FastAdmin项目根目录下创建websocket文件夹这个位置的选择很有讲究。我建议放在与application同级的目录这样既方便代码管理又能保持项目结构清晰。新建server.php文件内容如下?php require_once __DIR__ . /../vendor/autoload.php; use Workerman\Worker; use Workerman\Connection\TcpConnection; // 创建WebSocket服务器监听2345端口 $ws_worker new Worker(websocket://0.0.0.0:2345); // 启动4个进程对外提供服务 $ws_worker-count 4; // 保存所有客户端连接 $clients []; // 当有客户端连接时 $ws_worker-onConnect function(TcpConnection $connection) use ($clients) { $connection-onWebSocketConnect function(TcpConnection $connection) use ($clients) { $clients[$connection-id] $connection; echo New connection: {$connection-id}\n; }; }; // 消息处理逻辑 $ws_worker-onMessage function(TcpConnection $connection, $data) use ($clients) { foreach ($clients as $client) { $client-send($data); } }; // 连接关闭处理 $ws_worker-onClose function(TcpConnection $connection) use ($clients) { unset($clients[$connection-id]); echo Connection closed: {$connection-id}\n; }; Worker::runAll();这个基础版本实现了最简单的广播功能。在实际项目中你可能需要根据业务需求扩展消息处理逻辑比如添加身份验证、消息过滤等功能。3. 解决PHP版本冲突问题很多开发者会遇到PHP版本不匹配的问题特别是在宝塔环境下。明明在面板中安装了PHP7.4但命令行执行php -v却显示旧版本。这是因为系统环境变量没有更新。解决方法如下# 移除现有的PHP软链接 rm -f /usr/bin/php # 创建新的软链接指向PHP7.4 ln -sf /www/server/php/74/bin/php /usr/bin/php # 验证版本 php -v这个操作相当于告诉系统当我在命令行输入php时请使用7.4版本。我建议在执行前先备份原有链接以防需要回滚。4. 启动与管理WebSocket服务启动服务很简单但如何保持服务稳定运行才是关键。直接运行php websocket/server.php start但这种前台运行方式在SSH断开后服务就会停止。我们有几种解决方案方案一使用nohup后台运行nohup php websocket/server.php start 方案二使用Supervisor管理推荐在宝塔面板安装Supervisor添加守护进程配置如下命令php /www/wwwroot/你的项目路径/websocket/server.php start 目录/www/wwwroot/你的项目路径 用户wwwSupervisor的优势在于能够自动重启崩溃的服务还能记录日志是生产环境的首选方案。5. 前端UniApp连接实现UniApp端连接WebSocket需要特别注意跨平台兼容性。以下是经过实战检验的连接代码connet_sock(){ let socketUrl ws://你的服务器IP:2345; this.ST uni.connectSocket({ url: socketUrl, complete: (e) { console.log(e) }, fail: (f) { console.log(f) }, success: (s) { uni.onSocketOpen((res) { console.log(连接成功); // 可以在这里发送心跳包维持连接 }); uni.onSocketMessage((res) { try { const data JSON.parse(res.data); // 处理不同类型的消息 switch(data.type) { case SYSTEM_MSG: this.handleSystemMsg(data); break; case USER_MSG: this.updateChatList(data); break; } } catch(e) { console.error(消息解析错误, e); } }); uni.onSocketClose((res) { console.log(连接断开, res); this.reconnect(); // 实现重连逻辑 }); uni.onSocketError((res) { console.log(连接错误, res); this.reconnect(); }); } }); }消息发送示例sendMsg(content) { if(!this.ST) return; const msgId Date.now().toString(36) Math.random().toString(36).substr(2); const message { type: CHAT_MSG, content: content, msgId: msgId, timestamp: new Date().getTime() }; uni.sendSocketMessage({ data: JSON.stringify(message), success: (res) { this.addToLocalHistory(message); // 本地消息记录 }, fail: (err) { uni.showToast({ title: 发送失败, icon: none }); } }); }6. 安全组与防火墙配置这是最容易出问题的环节之一。即使代码完全正确如果网络配置不当连接依然会失败。需要检查三个层面的配置1. 宝塔面板安全设置进入安全选项卡放行2345端口或你自定义的端口如果需要域名访问还要配置SSL证书2. 服务器提供商安全组阿里云/腾讯云等平台都有安全组设置添加入站规则允许TCP:2345出站规则通常默认放行3. 服务器本地防火墙# 查看防火墙状态 sudo ufw status # 开放端口 sudo ufw allow 2345/tcp测试端口是否通畅telnet 你的服务器IP 2345如果连接失败按照上述三个层面逐一排查。我曾经花了半天时间才发现是云平台安全组没配置这个教训希望大家引以为戒。7. 常见问题排查指南问题一连接后立即断开可能原因心跳机制未实现导致连接超时Nginx代理配置不当如果使用反向代理 解决方案# Nginx代理配置示例 location /websocket { 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 Host $host; proxy_read_timeout 3600s; }问题二消息延迟严重优化方案减少广播范围只发送给相关用户使用WorkerMan的sendToAll替代循环发送检查服务器带宽是否充足问题三内存泄漏监控命令# 查看PHP进程内存占用 ps aux | grep php预防措施定期重启服务可通过Supervisor配置避免在onMessage中创建大对象使用内存监控工具如php-meminfo8. 性能优化建议当用户量增长后原始的单机部署可能遇到性能瓶颈。以下是几种优化方案1. 多端口监听$worker new Worker(websocket://0.0.0.0:2345); $worker-count 8; // 根据CPU核心数调整2. 业务拆分将广播消息和单播消息分开处理重要消息走独立通道3. 使用GatewayWorker如果需要更强大的功能可以考虑基于Workerman的GatewayWorker框架它提供了分布式部署支持自动心跳检测客户端分组管理部署示例$gateway new Gateway(websocket://0.0.0.0:2345); $gateway-name ChatGateway; $gateway-count 4; $gateway-lanIp 127.0.0.1; $gateway-startPort 2300; $gateway-pingInterval 30;4. 监控方案建议添加简单的监控脚本$worker-onWorkerStart function($worker) { // 定时上报状态到监控系统 Timer::add(10, function() { $status [ memory memory_get_usage(true), connections count($clients), time date(Y-m-d H:i:s) ]; file_put_contents(/tmp/websocket_status.log, json_encode($status)); }); };在实际项目中我通常会结合宝塔的计划任务定期检查这个日志文件当发现异常时自动报警。这种简单的监控机制已经能够预防大部分线上问题。