Swoole是PHP一個擴展,但和其餘擴展只提供接口、函數不一樣,Swoole從新定義PHP,接管並從新處理數據,將處理好的數據返回給PHP,支持百萬TCP鏈接,同時支持異步/同步/協程等功能php
Swoole採用多進程架構模型,比多線程架構更方便,不存在線程安全問題,缺點是進程與進程通訊沒有線程方便,另外PHP-FPM,Nginx採用的也是多進程模型,學習起來仍是容易接受。git
異步Worker進程是Swoole提供的一個非阻塞進程,投遞一個異步任務到異步進程,執行完畢當即返回,異步進程能夠繼續處理新請求,進程間沒有加鎖爭搶,性能異常優良。利用以上特性,能夠用來處理耗時較長的事務。github
傳統推送經過設置自動執行,或者手動執行讀取運營後臺設定數據,寫入隊列(可選),接着將數據推給第三方,第三方將推送結果告知程序,這個告知的過程一般以對方網絡穩定決定了推送效率,推送短板也在這塊。sql
異步任務運用在從隊列讀取數據過程當中,開啓多個進程讀取數據,接着發送數據給第三方,只要開啓合適數量的進程,推送速度極快。數據庫
話很少說,擼起代碼就是幹數組
一、註冊定時器,寫入任務安全
if ($workerId == 0) { Timer::Loop(1 * 1000, function () { PushLogic::addQueue(); }); }
<?php namespace App\Logic; use App\Logic\Queue; class PushLogic { const REDIS_KEY = 'push_list'; public static function addQueue($task) { Queue::push(self::REDIS_KEY, $task); } }
二、註冊定時器 獲取任務swoole
if ($workerId == 1) { Timer::Loop(5 * 1000, function () { $share = ShareMemory::getInstance(); // 啓用16個異步Task進程 if ($share->get(Sys::PUSH_TASK_NUM) < 16) { AsyncTaskManager::getInstance()->add(PushTask::class); } }); }
三、封裝異步執行邏輯網絡
<?php namespace App\Logic; use App\Logic\Queue; class PushLogic { conse REDIS_KEY = 'push_list'; public static function handle($task) { // 進程數據隔離 文件鎖 記錄異步Task進程數量 $share = ShareMemory::getInstance(); $share->startTransaction(); $key = Sys::PUSH_TASK_NUM; $share->set($key, $share->get($key) + 1); $share->commit(); while (true) { $task = Queue::pop(self::REDIS_KEY); // 調用GCM或APNS邏輯 Gcm::send($task); } $share->startTransaction(); $share->set($key, $share->get($key) - 1); $share->commit(); } }
至此主要功能已處理完畢,具體推送結果能夠根據實際狀況存入Redis、Swoole內存表、數據庫
注:推送結果不要存在全局變量或者靜態變量,由於不一樣進程內存隔離多線程
傳統推送耗時:30分鐘 異步多任務:3分鐘