1. 程式人生 > >php swoole 多程序傳送微信模板訊息\郵件

php swoole 多程序傳送微信模板訊息\郵件

   年前接到需求做了一個功能,給快到期的微信使用者傳送模板訊息,提醒續費.

    首先拿到快到期的使用者, 每天大概800-2000不等,感覺壓力不是很大,直接foreach 陣列 然後傳送,經常出現請求超時 也就是502的問題,緊接著運營同事提出要針對一大批使用者 推模板訊息,年前搞一波促銷,量每天在1萬左右,於是楞沖沖的 直接做了個上傳功能,給運營人員直接上傳發送,然後用是無限的502bad way.

    此時 ,感覺模板訊息數量上去了,需要優化,於是採用另外一種方案,redis佇列+守護程序,將上傳的資料跟傳送的解耦, 守護程序檢測redis佇列中是否存在需要傳送的資料,如果存在就開始 一條條往外取,然後傳送.此方案感覺是運營人員不用管結果,肯定能傳送成功,但是時間比較長,量大了 很長時間才發完, 那麼就出現了另外一個問題,發出去的時間不用,想在使用者開啟微信的最高峰時間段傳送給使用者.好繼續優化!

 此時改用php+swoole 來進行多程序非同步處理,既然一個程序慢,那咱就多開幾個,於是16個程序一起非同步傳送,1萬模板訊息 10分鐘之內發完,基本改造完成.

下面貼出程式碼 demo

首先啟動server.php

客戶端

class Client
{
    public function send($msg){
        $client = new swoole_client(SWOOLE_SOCK_TCP);
        //連線到伺服器
        if (!$client->connect('127.0.0.1', 9501, 0.5))
        {
            $this->write("connect failed.");
        }
        //向伺服器傳送資料
        if (!$client->send($msg))
        {
            $this->write("send ".$msg." failed.");
        }
        //關閉連線
        $client->close();
    }
    private function write($str){
        $path = "/sys.log";
        
        $str = "[".date("Y-m-d H:i:s")."]".$str;
        $str .= PHP_EOL;
        file_put_contents($path,$str,FILE_APPEND);
    }

}

服務端

<?php
$serv = new swoole_server("127.0.0.1", 9501);


//設定非同步任務的工作程序數量
$serv->set(array('task_worker_num' =>16));


//監聽資料接收事件
$serv->on('receive', function($serv, $fd, $from_id, $data) {
    //投遞非同步任務
    $task_id = $serv->task($data);//非阻塞
    echo "同步程式碼執行完成\n";
});


//處理非同步任務
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
    handleFun($data);
    //返回任務執行的結果
    $serv->finish("finish");
});


//處理非同步任務的結果
$serv->on('finish', function ($serv, $task_id, $data) {
    echo "非同步任務執行完成";
});


$serv->start();


function handleFun($data){
       
    $data=json_decode($data,true);

   foreach ($data  as $key => $value) {
    
     echo  json_encode($value);
      $url="xxxx";//呼叫傳送模板訊息介面,服務端沒辦法直接獲取微信的介面的一些資料,此處做了一些加密
         $postUrl = $url;
        $curlPost = $value;

        $ch = curl_init(); //初始化curl
        curl_setopt($ch, CURLOPT_URL, $postUrl); //抓取指定網頁
        curl_setopt($ch, CURLOPT_HEADER, 0); //設定header
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求結果為字串且輸出到螢幕上
        curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
        $data = curl_exec($ch); //執行curl
        curl_close($ch);
       
   }
  

}

呼叫client.php

<?php

include dirname(__FILE__).'/client.php';

$params=""//介面資料

$msg = json_encode($params);

$client = new Client();
$client->send($msg);
echo "[".date("Y-m-d H:i:s")."]執行完成".PHP_EOL;