topthink/think-swoole 擴展包的使用 之 Task

本想本身適配的,奈何keng貌似很多,因此果斷選擇官方提供的包來適配233。。。php

默認條件:thinkphp5.1.*版本下,且安裝了swoole擴展git

主要演示:task 任務的投遞github

友情提示:在swoole啓動框架時,需注意靜態變量的使用,會常駐內存(好比單例的變量),... 無圖言卵,我麼的口號是有圖有真相(搞事)
web

如下是swoole下單例模式發送郵件:thinkphp

請看收件人, 圖一給 994xxx@qq.com發送郵件; 圖二給 159xxx@qq.com 發送郵件,其收件人卻有兩(包含圖一中的帳號)。json

找尋緣由: 
因爲使用的是單例模式郵件發送,其$phpmail對象只實例化一次 ,圖一當添加收件人時 $shouJianRen[ ] = 994xxx@qq.com 結束;圖二給 159xxx@qq.com 發送郵件,因爲$phpmail對象不會再次實例化 也就是此時他的屬性 $shouJianRen 已再也不是空值,繼而會繼續疊加第二個收件人,因此也就形成了第二次給 159xxx@qq.com發送時會有兩個收件人。 
 
如下開始正文。。。

1、安裝

composer require topthink/think-swoole=2.0.*

2、使用

若是你要運行 swoole 的 http 服務器來啓動 thinkPHP框架,執行服務器

php think swoole

默認啓動完成後,會在0.0.0.0:9501啓動一個HTTP Server,能夠直接訪問當前的應用。websocket

swoole的參數能夠在應用配置目錄下的 swoole.php 裏面配置,配置詳情見 thinkPHP官網swoole

擴展中定義了 onWorkerStart和 onRequest事件回調方法(若是不熟悉請不要隨意替換),若是你須要自定義swoole的事件回調方法,能夠在配置文件中使用閉包定義。閉包

如下是個人配置(自定義了task任務回調):

use app\common\lib\utils\Task;
use think\facade\Env;
use think\facade\Log;

// +----------------------------------------------------------------------
// | Swoole設置 php think swoole命令行下有效
// +----------------------------------------------------------------------
return [
    // 擴展自身配置
    'host'                  => '0.0.0.0', // 監聽地址
    'port'                  => 9501, // 監聽端口
    'mode'                  => '', // 運行模式 默認爲SWOOLE_PROCESS
    'sock_type'             => '', // sock type 默認爲SWOOLE_SOCK_TCP
    'server_type'           => 'http', // 服務類型 支持 http websocket
    'app_path'              => '', // 應用地址 若是開啓了 'daemonize'=>true 必須設置(使用絕對路徑)
    'file_monitor'          => false, // 是否開啓PHP文件更改監控(調試模式下自動開啓)
    'file_monitor_interval' => 2, // 文件變化監控檢測時間間隔(秒)
    'file_monitor_path'     => [], // 文件監控目錄 默認監控application和config目錄

    // 能夠支持swoole的全部配置參數
    'pid_file'              => Env::get('runtime_path') . 'swoole.pid',
    'log_file'              => Env::get('runtime_path') . 'swoole.log',
    'document_root'         => Env::get('root_path') . 'public',
    'enable_static_handler' => true,
    'timer'                 => true,//是否開啓系統定時器
    'interval'              => 500,//系統定時器 時間間隔
    'task_worker_num'       => 1,//swoole 任務工做進程數量

    /**
     * 自定義投遞任務
     * @param swoole_server $serv
     * @param int $taskId
     * @param int $srcWorkerId
     * @param mixed $data
     */
    'Task' => function($serv, $taskId, $srcWorkerId, $data){
        $taskObj = new Task();
        $classMethods = get_class_methods(Task::class);
        if (!in_array($data['method'], $classMethods)) {
            return 'method:'.$data['method'].' not find in'.Task::class;
        }
        return call_user_func_array([$taskObj, $data['method']], $data['params']);
    },
    /**
     * onTask事件中沒有調用finish方法或者return結果,worker進程不會觸發onFinish
     * @Param swoole_server $serv
     * @param int $taskId 任務的ID
     * @param string $data 任務處理的結果內容
     */
    'Finish' => function ($serv, $taskId, $data) {
//        echo 'taskId:' . $taskId . PHP_EOL;
        echo 'Finished:' . $data;
        Log::record($data);
    }
];

 

實現任務的投遞兩種方法實現

Index控制器中:

<?php

namespace app\index\controller;

use app\common\lib\task\SmsTask;
use app\common\lib\utils\Tool;use think\Controller;
use think\Request;

class Index extends Controller
{
public function sendSms(Request $request) { $result = $this->validate($request->post(), ['mobile' => 'require|mobile']); if (true !== $result) { return Tool::json('', $result, 250); } $mobile = $request->post('mobile'); // 一、使用topthink/swoole自帶的任務投遞方式,傳遞參數必須是對象或者swoole回調函數 // $smsObj = new SmsTask($mobile); // app('swoole')->task($smsObj); // app('swoole')->task($smsObj); // 二、自定義任務投遞方式 app('swoole')->task(Tool::taskParam('sendSms', (array)$mobile)); return Tool::json('', '短信發送成功'); }

 

SmsTask.php

使用系統默認的回調模板,

且投遞的參數必須是對象或者swoole回調函數,

投遞任務後默認會執行 run()方法或者swoole回調函數

<?php


namespace app\common\lib\task;

use Fairy\SmsSender;
use think\facade\Config;
use think\swoole\template\Task;

/**
 * 使用 topthink/swoole 自帶的Task任務
 * Class SmsTask
 * @package app\common\lib\task
 */
class SmsTask extends Task
{
    private $mobile;

    public function initialize($args)
    {
        // TODO: Implement initialize() method.
        $this->mobile = $args[0];
    }

    public function run($serv, $taskId, $fromWorkerId)
    {
        // TODO: Implement run() method.
        $smsObj = SmsSender::getInstance(Config::get('mail.'));
        $bool = $smsObj->send($this->mobile);
        if ($bool) {
            return 'send sms to ' . $this->mobile . ' success';
        } else {
            return $smsObj->getError();
        }
    }
}

 

Task.php

配合swoole.php中自定義的 task 回調函數使用

<?php

namespace app\common\lib\utils;

use Fairy\SmsSender;use think\facade\Config;

/**
 * 異步任務類
 * Class Task
 * @package app\common\lib\utils
 */
class Task
{
    /**
     * 異步發送短信
     * @param $mobile
     * @return mixed|string
     * @throws \ErrorException
     */
    public function sendSms($mobile)
    {
        $smsObj = SmsSender::getInstance(Config::get('sms.'));
        $bool = $smsObj->send($mobile);
        if ($bool) {
            return 'send sms to ' . $mobile . ' success';
        } else {
            return 'send sms to ' . $mobile . ' failed: ' . $smsObj->getError();
        }
    }
}

 

異步發送短信執行流程(拿自定義的task來舉例):

  1. 配置swoole.php的自定義task函數
  2. 訪問控制器 index/index/index 下的 sendSms() 方法 會投遞一個任務,傳遞一些參數給task,此時接口數據已返回且短信發送任務也已投遞
  3. task回調,也就是執行 swoole.php 中的配置的 task 函數
  4. 執行 finish 回調
  5. 打完收工,你學會了嗎

 

參考:

https://www.kancloud.cn/manual/thinkphp5_1/675277

https://github.com/top-think/think-swoole/tree/v2.0.17

https://www.imooc.com/article/31751

相關文章
相關標籤/搜索