点击蓝字 关注我们
线上电玩项目开发过程总结报告
一套稳定、高效、可扩展的线上电玩系统核心由服务端、数据库、硬件终端三大部分构成,实现了用户游戏、上分下分、数据统计、设备监控等核心功能。项目对高并发、低延迟、数据一致性和硬件通信稳定性有着极高的要求。
PHP7.4 + ThinkPHP5: 作为主要的HTTP API和业务逻辑处理框架。ThinkPHP5提供了完善的MVC结构和丰富的类库,能极大提高业务代码的开发效率,非常适合处理用户注册、登录、订单、数据查询等Web请求。
Workerman: 作为Socket服务器,用于与硬件终端建立和维护TCP长连接。它是本项目技术选型的核心亮点。选择Workerman而非Swoole,主要因其对PHP原生代码兼容性更好,学习曲线相对平缓,且同样能提供高性能的网络通信能力,完美满足了硬件通信所需的常驻内存和异步非阻塞特性。
MySQL5.7: 作为核心关系型数据库,用于存储用户信息、订单记录、游戏日志、设备信息等结构化数据。其稳定性和事务特性保证了核心业务数据的一致性。
Redis: 作为高性能缓存和内存数据库,主要用于:
Session共享: 在Workerman多进程环境下存储用户连接状态。
缓存热点数据: 如游戏配置、用户分数等,极大减轻MySQL压力。
消息队列: 用于处理异步任务,如订单下发、日志记录等,提升系统响应速度。
实时数据存储: 存储用户当前分数、设备状态等高频变化的数据。
TCP协议: 采用TCP协议与硬件终端进行通信,确保了数据传输的可靠性、有序性和完整性,相比U协议更适合需要保证指令必达的金融级交互场景。
系统总体上分为两层:
HTTP层 (Web层): 基于ThinkPHP5,面向APP/管理后台,处理所有标准的HTTP请求,如用户API、管理API。
Socket层 (网关层): 基于Workerman,专门负责与所有硬件终端保持TCP长连接,处理所有硬件上行和下行的指令。
两层之间通过Redis和MySQL进行数据交换和状态同步。
开发了一个独立的Gateway服务,作为所有硬件终端的统一接入点。
每个终端上电后主动连接到Gateway服务,并进行身份认证(如发送设备SN码和密钥)。
Gateway服务维护一个fd(文件描述符)与设备ID的映射关系,存储在Redis中,使得业务逻辑层可以通过设备ID精准地向指定终端下发指令。
实现了心跳检测机制,定期检查终端连接是否存活,及时清理僵尸连接,释放资源。
与硬件团队共同制定了紧凑、高效的二进制TCP通信协议。
数据包结构: 包起始符 + 数据长度 + 协议版本 + 指令码 + 数据体 + 校验码 + 包结束符。
指令码(CMD):定义了各种操作,如0x01=心跳、0x10=上传游戏结果、0x11=下发开始游戏指令等。
数据序列化: 数据体部分采用JSON格式,兼顾可读性和灵活性。
校验机制: 采用CRC16或MD5等校验算法,保证数据在传输过程中不被篡改。
1.HTTP请求: 用户通过APP扫码,ThinkPHP5接口收到“开始游戏”请求,生成订单并预扣款。
2.指令下发: ThinkPHP5业务层通过Redis队列,向Workerman网关服务发送一个“下发游戏指令”的异步任务(包含设备ID和指令信息)。
3.网关处理: Workerman从队列中取出任务,根据设备ID查询Redis找到对应的TCP连接“fd“,将指令按协议格式打包后下发至硬件终端。
4.硬件执行: 终端收到指令,启动游戏。
5.结果上报: 游戏结束后,终端通过TCP连接将结果数据上报给Workerman网关。
6.结果处理: Workerman解析数据,验证校验码,然后将结果信息存入Redis队列。
7.订单结算: ThinkPHP5从队列中获取结果,更新订单状态为成功,并更新用户余额。同时,向APP推送游戏结果消息。
设备实时状态(是否在线、当前状态)存储在Redis中,供APP和管理后台实时查询。
所有资金变动均通过MySQL事务保证一致性,确保“钱-分-游戏结果”三者数据完全匹配。
三、遇到的问题与解决方
现象: 硬件端连续发送多条数据时,服务端可能一次收到多条(粘包),或一条消息被拆成多次接收(拆包)。
解决方案: 在协议中设计了数据长度字段。Workerman在接收数据时,先读取固定长度的包头,解析出本次数据体的实际长度,然后根据这个长度值去读取完整的数据体,从而完美地解决了粘包拆包问题。
现象: 用户Client A可能连接到Worker进程1,而后续的指令消息可能被发往Worker进程2,导致进程2无法识别fd。
解决方案: 使用Redis存储全局的fd->设备ID和设备ID->fd的映射关系。所有Worker进程都操作统一的Redis,从而实现进程间共享连接信息。
现象: 多个用户同时操作一台设备,或分数并发更新可能导致数据错乱。
解决方案:
数据库层面: 对关键更新操作(如用户余额增减)使用MySQL悲观锁(“SELECT ... FOR UPDATE“)或乐观锁。
缓存层面: 对Redis的写操作使用“lua“脚本,确保原子性。
现象: 硬件终端可能因网络波动突然断线。
解决方案: 实现断线重连机制,要求硬件端在断线后自动尝试重新连接。在服务端设置心跳超时,及时清除无效连接并更新设备状态为“离线”。
通过“PHP7.4 + ThinkPHP5 + Workerman“的组合,成功地构建了一个兼具高开发效率和高运行性能的线上电玩系统。Workerman完美地承担了TCP网关的重任,解决了PHP传统架构无法保持长连接的问题。
在PHP中利用Workerman可以极大地扩展应用场景,处理网络实时通信。
清晰界定HTTP和Socket的职责边界,让系统更稳定、更易于维护。
良好的通信协议设计是硬件项目稳定的基石。
Redis在整个架构中扮演了“神经系统”的角色,至关重要。
1. 服务治理: 引入微服务架构,将网关服务、用户服务、订单服务拆解,提升系统容错性和扩展性。
2.控预警: 搭建更完善的监控系统(如Prometheus+Grafana),对TCP连接数、消息延迟、系统负载等进行实时监控和报警。
3.协议升级: 考虑使用更高效的数据序列化方案,如Protocol Buffers,以进一步减少网络流量和提高解析效率。
4.灰度发布: 实现硬件终端指令的灰度发布机制,降低大规模升级带来的风险。
咨询热线:13143708687

