首頁 >php框架 >ThinkPHP >Think-Swoole之Task 非同步任務

Think-Swoole之Task 非同步任務

藏色散人
藏色散人轉載
2020-10-27 13:39:093935瀏覽

Think-Swoole之Task 非同步任務

使用場景

#在Server 程式中如果需要執行很耗時的操作,例如一個聊天伺服器發送廣播,Web伺服器中發送郵件。如果直接去執行這些函數就會阻塞目前進程,導致伺服器回應變慢。例如:使用者註冊場景,完成註冊並發送啟動郵件的功能,需要以下幾步:

客戶端提交POST 資料-> 伺服器取得到資料-> 完成註冊將使用者資料寫入資料庫- > 傳送帳號啟動郵件-> 回傳客戶端提示註冊成功。

這個業務邏輯是沒有問題的,但是由於發送郵件是一個耗時操作(例如2-3s)並且會同步阻塞程序的執行,直到發送成功以後響應到客戶端提示註冊成功。這個過程中用戶從提交到最後得到註冊成功的提示估計需要4s左右,一次請求響應需要4s這肯定是不合理的!

現在使用Task 非同步任務投遞可以大幅提升使用者體驗,大致流程:

客戶端提交POST 資料-> 伺服器取得到資料-> 完成註冊將使用者資料寫入資料庫-> 馬上返回客戶端提示註冊成功。

在註冊成功同時投遞一個 Task 任務 -> 非同步完成郵件發送的耗時操作 (這部分時間用戶是無感知的,因為很早已經回應回客戶端了)。

如何使用 Think-Swoole 的 Task 非同步任務的步驟

定義事件監聽類別(php think make:listener 類別名稱)。

app/event.php 檔案中定義 swoole.task 的事件監聽。

取得到 Swoole/Server 物件呼叫 task 方法(參數中傳遞剛剛定義的監聽類別)。

在剛剛定義的事件監聽類別的 handle 方法中定義觸發回呼邏輯程式碼。

調用觸發 task swoole.finish任務完成後的 finish 方法(需要才調用,非必須)。

進行示範

首先,專案根目錄建立郵件傳送事件:

php think make:listener EmailTask

然後定義已建立的郵件傳送事件:

app/event.php
'listen'    => [
    'AppInit'  => [],
    'HttpRun'  => [],
    'HttpEnd'  => [],
    'LogLevel' => [],
    'LogWrite' => [],
    'swoole.task' => [
        app\listener\EmailTask::class,
    ],
//  'swoole.finish' => [
//      app\listener\EmailTaskFinish::class,
//  ],
],

其中swoole.task 這個鍵名是Task 任務固定寫法不能隨意命名。

接著,我們在負責使用者註冊的控制器內,透過Swoole/Server 類別來呼叫Task 非同步任務,當然,我們要先完善EmailTask​​.php 的邏輯程式碼:

app/ listener/EmailTask​​.php

<?php
declare (strict_types = 1);
namespace app\listener;
class EmailTask
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
{
        echo "开始发送邮件:".time();
        //模拟耗时 3 秒,测试是否在响应事件内
        sleep(3);
        echo "邮件发送成功:".time();
        // 可以调用 finish 方法通知其他事件类,通知当前异步任务已经完成了(非必须调用)
        // 参数 $event 是 Swoole\Server\Task 类的一个对象 可以调用 finish 方法触发 task 任务的 onFinish 事件
        // $event -> finish(\app\listener\EmailTaskFinish::class);
    }
}

註冊方法app/controller/Register.php

<?php
namespace app\controller;
use app\BaseController;
class Register extends BaseController
{
    public function register(\Swoole\Server $server)
{
        if($this -> request -> isPost()){
            $data = $this -> request -> post();
            //TODO 调用验证类验证数据
            //TODO 将注册信息插入数据库
            // 这里调用 Task 异步任务
            $server -> task(\app\listener\EmailTask::class);
            // 方式二
//            $manager = app(&#39;\think\swoole\Manager&#39;);
//            $manager -> getServer() -> task(\app\listener\EmailTask::class);
            return "注册成功!".time();
        }
    }
}

註冊業務中,插入資料庫後,呼叫了發送郵件非同步任務,在EmailTask​​.php 模擬發送郵件需要3 秒鐘。

開啟Think-Swoole 服務,存取註冊的方法,測試一下發送郵件的時間是否計入用戶註冊方法內:

Think-Swoole之Task 非同步任務

可見,郵件發送的3 秒鐘是異步進行的,使用者並無感知。

另外,還有個swoole.finish 事件,用來通知其他事件當前非同步任務已經完成了,同樣需要建立事件,在app/event.php 中定義swoole.finish,上述範例程式碼已經示範了。

以上是Think-Swoole之Task 非同步任務的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:阿dai哥。如有侵權,請聯絡admin@php.cn刪除