PHP结合Redis队列削峰填谷:打造高并发个人微信消息发送网关
在许多传统的PHP业务系统中,由于PHP本身多进程/同步阻塞的特性,当遇到需要同时向数千个微信用户推送通知的场景时,直接发送极易导致Web服务器进程被迅速占满,进而引发网关超时。本文将分享如何利用PHP结合Redis队列,实现异步、削峰填谷的微信消息发送网关。
一、 架构改造思路
请求解耦:业务代码不再直接调用外部发送接口,而是将待发送的消息结构化后压入Redis队列中,并瞬间返回响应。
守护进程消费:编写一个常驻内存的PHP CLI脚本,持续从Redis队列中Pop数据,并按照预设的限流规则进行发送。
异常重试:当某条消息因网络原因发送失败时,可进行二次重试。
二、 核心代码实现
以下是基于PHP实现的Redis队列消费者核心逻辑。
<?php class WeChatQueueWorker { private $redis; private $queueName = 'wechat_send_queue'; private $apiUrl = 'http://127.0.0.1:8080/v1/message/send'; private $apiToken = 'your_api_token_here'; public function __construct() { $this->redis = new Redis(); $this->redis->connect('127.0.0.1', 6379); } public function run() { echo "微信消息队列消费者已启动...\n"; while (true) { try { $taskData = $this->redis->brPop($this->queueName, 5); if (!empty($taskData)) { $payload = json_decode($taskData[1], true); if ($payload) { $this->handleSend($payload); } } } catch (\Exception $e) { echo "捕获到异常: " . $e->getMessage() . "\n"; sleep(2); } } } private function handleSend(array $payload) { $wxid = $payload['wxid'] ?? ''; $message = $payload['message'] ?? ''; echo "正在发送给 [{$wxid}] ...\n"; $postData = json_encode([ 'to' => $wxid, 'content' => $message ]); $ch = curl_init($this->apiUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->apiToken, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode === 200) { echo "发送成功: {$wxid}\n"; } else { echo "发送失败,HTTP状态码: {$httpCode}\n"; } usleep(500000); } } if (php_sapi_name() === 'cli') { $worker = new WeChatQueueWorker(); $worker->run(); }三、 生产环境部署建议
在生产环境中,建议使用进程管理工具来托管该PHP脚本,确保进程在意外挂掉时自动拉起,从而保障高可用性。