think-queue 3.0實戰教程:打造一個定時扣費系統

前言

截止撰稿之時,ThinkPHP6.0已經進入RC3階段。按ThinkPHP做者流年的計劃,ThinkPHP6.0預計將會在今年秋季擇機發布正式版,RC3將多是正式版以前的最後一個或者倒數第二個RC版本,這也就意味着,ThinkPHP6.0已經日趨完善穩定,是一個值得嘗試的候選版本了。php

故此,隨之有着重大變化的think-queue擴展也已經升級發佈了接近正式版的3.0.2。那麼已經用think-queue上了生產環境的小夥伴們確定很想知道,think-queuehtml

3.0是否已經能夠嚐鮮了?本期小編將帶你們用think-queue 3.0.2的定時隊列來打造一個定時扣費系統來告訴你答案。linux

PS:本人文中若有錯誤或者不失之處,還請海涵,歡迎各位大牛隨時批評指導。laravel

準備工做

使用think-queue隊列,必須具有如下條件:git

1:一個基於liunx系統的server,windows亦可但不推薦;github

2:redis服務端。建議5.0版本,web

參考文章:https://www.jianshu.com/p/fe6...redis

新手推薦使用寶塔面板,https://www.bt.cn/download/li... ,以省去精力和減小配置編譯形成的服務端各類常見問題。thinkphp

3:composer包管理器數據庫

可參考:https://www.phpcomposer.com

推薦鏡像源:https://mirrors.aliyun.com/co...,在此感謝阿里雲的貢獻。

4:一個redis客戶端,Windows開發者推薦在如下項目裏選擇使用

https://github.com/uglide/Red...

https://github.com/qishibo/An...

https://github.com/cinience/R...

以及windows自帶的Windows PowerShell。

對於think-queue不是很熟悉和了解的,請務必先閱讀下面這邊教程後再回來繼續閱讀:

https://github.com/coolseven/...

安裝thinkhp和think-queue

1:首選建立thinkphp6.0新的項目,參考https://www.kancloud.cn/manua...

composer create-project topthink/think=6.0.x-dev tp

2:使用think-queue 3.0.2

https://packagist.org/package...

composer require topthink/think-queue

也能夠項目根目錄下composer.json文件添加配置項

"require": {
        "php": ">=7.1.0",
        "topthink/framework": "6.0.*-dev",
        "topthink/think-view": "^1.0",
        "symfony/var-dumper":"^4.2",
        "topthink/think-queue": "^3.0"
    },

3:檢查是否安裝成功

在項目根目錄下運行

php think

看到
圖片描述

就表示think-queue已經安裝成功。

接下來就要進行下一步:建立項目的數據庫,結構我已經準備好了

用戶會員表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用戶名',
  `nickname` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '暱稱',
  `realname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '姓名',
  `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密碼',
  `create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '註冊時間',
  `update_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '更新時間',
  `login_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '登錄時間',
  `login_count` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '登錄次數',
  `login_ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '登陸ip',
  `vip` tinyint(2) UNSIGNED NULL DEFAULT 0 COMMENT 'vip等級',
  `vip_join` int(10) UNSIGNED NULL DEFAULT 0 COMMENT 'vip加入時間',
  `vip_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT 'vip過時時間',
  `ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '註冊ip',
  `status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '狀態1:正常2:禁用3:臨時',
  `lock_uid` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '封禁人',
  `lock_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '封禁時間',
  `lock_tips` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '封禁緣由',
  `back_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '解封時間',
  `group` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '身份1:普通2:管理員3:代理4:合做方5:渠道商',
  `group_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '身份過時',
  `safe_level` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '安全等級',
  `safe_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '密保安全碼',
  `safe_token` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '密保令牌1:未2:是',
  `safe_device` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '密保設備1:未2:是',
  `safe_phone` bigint(11) UNSIGNED NULL DEFAULT 0 COMMENT '密保手機',
  `safe_email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '密保郵箱',
  `verify_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '找回校驗碼',
  `verify_lock` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '找回鎖定',
  `verify_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '校驗碼過時',
  `money` decimal(10, 3) UNSIGNED NOT NULL DEFAULT 0.000 COMMENT '餘額',
  `give` decimal(10, 3) UNSIGNED NOT NULL DEFAULT 0.000 COMMENT '增送',
  `brokerage` decimal(10, 3) UNSIGNED NOT NULL DEFAULT 0.000 COMMENT '佣金',
  `server` int(10) UNSIGNED NOT NULL DEFAULT 10 COMMENT '服務器',
  `gold` tinyint(8) UNSIGNED NOT NULL DEFAULT 0 COMMENT '金幣',
  `credits` tinyint(8) UNSIGNED NOT NULL DEFAULT 0 COMMENT '積分',
  `union_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '微信',
  `unionid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'QQ',
  `inviters` tinyint(5) UNSIGNED NOT NULL DEFAULT 0 COMMENT '邀請次數',
  `inviter_id` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '邀請人',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `id`(`id`, `username`, `realname`, `vip`, `group`, `money`, `create_time`) USING BTREE COMMENT '聯合索引'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶表' ROW_FORMAT = Dynamic;

日誌表

DROP TABLE IF EXISTS `logs`;
CREATE TABLE `logs`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `uid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用戶id',
  `subid` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '主機id',
  `op_id` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '操做人id',
  `type` tinyint(2) UNSIGNED NOT NULL DEFAULT 1 COMMENT '類型1:會員2:管理3:系統5:財務',
  `time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '時間',
  `ip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '登陸ip',
  `content` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '日誌內容',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_uid_type_time`(`uid`, `type`, `time`, `op_id`, `subid`) USING BTREE COMMENT '聯合索引'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '日誌表' ROW_FORMAT = Dynamic;

用戶主機表

DROP TABLE IF EXISTS `server`;
CREATE TABLE `server`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `uid` int(10) UNSIGNED NOT NULL COMMENT '所屬用戶',
  `status` int(2) UNSIGNED NOT NULL DEFAULT 2 COMMENT '狀態1:已中止2:運行中3:已過時4:需續費5:已刪除6:異常',
  `time` int(10) UNSIGNED NOT NULL COMMENT '建立時間',
  `op` int(4) UNSIGNED NULL DEFAULT 0 COMMENT '操做人',
  `op_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '操做時間',
  `subid` bigint(11) UNSIGNED NULL DEFAULT 0 COMMENT '實例id',
  `ip_address` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'IPv4',
  `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'root密碼',
  `snapshotid` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '快照id',
  `port` int(10) UNSIGNED NULL DEFAULT 22 COMMENT '端口',
  `ips` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '高防IP',
  `enable_ipv6` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'IPv6',
  `ipv6` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'IPv6地址',
  `dcid` int(5) UNSIGNED NULL DEFAULT 0 COMMENT '位置',
  `osid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操做系統',
  `arch` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '系統類型',
  `vpsplanid` double(32, 0) UNSIGNED NULL DEFAULT 0 COMMENT '配置規格',
  `hostname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '自定義名稱',
  `ddos` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'DDOS',
  `appid` int(6) UNSIGNED NULL DEFAULT 0 COMMENT '預裝應用',
  `destroy` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '刪除時間',
  `month` int(3) UNSIGNED NULL DEFAULT 0 COMMENT '購買時長',
  `deduction` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '扣費次數',
  `money` decimal(10, 3) UNSIGNED NULL DEFAULT 0.000 COMMENT '費用',
  `deduction_time` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '扣費時間',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '主機表' ROW_FORMAT = Compact;

流水錶

DROP TABLE IF EXISTS `account`;
CREATE TABLE `account`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `uid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用戶id',
  `type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '類型1:收入2:支出',
  `class` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '種類1:餘額',
  `money` decimal(10, 3) UNSIGNED NULL DEFAULT 0.000 COMMENT '金額',
  `way` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '來源1:系統2:充值3:提現4:主機',
  `style` tinyint(2) UNSIGNED NOT NULL DEFAULT 1 COMMENT '分類1:系統2:支付寶3:微信4:卡密',
  `timestamp` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '時間鎖',
  `subid` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '實例id',
  `rechargeid` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '充值id',
  `trade` char(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '流水號',
  `card_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '卡密id',
  `op` tinyint(2) UNSIGNED NOT NULL DEFAULT 1 COMMENT '操做人',
  `content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '內容',
  `time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '時間',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `idx_timestamp`(`timestamp`) USING BTREE COMMENT '時間鎖',
  INDEX `idx_uid_type_class_way_style_subid_rechargeid`(`uid`, `type`, `class`, `way`, `style`, `subid`, `rechargeid`, `trade`, `money`) USING BTREE COMMENT '聯合索引'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '流水錶' ROW_FORMAT = Dynamic;
系統會員註冊登陸代碼部分略過,請本身補充,也能夠在文章末尾下載本教程對應實例代碼。

開始使用隊列

本教程think-queue隊列使用的是redis驅動方式,請務必先配置好redis,配置文件在config文件夾下面的queue.php,別弄錯了

return [
    'default' => 'redis',
    'connections' => [
        'sync' => [
            'driver' => 'sync',
        ],
        'database' => [
            'driver' => 'database',
            'queue' => 'default',
            'table' => 'jobs',
        ],
        'redis' => [
            'driver' => 'redis',
            'queue' => 'default',
            'host' => '127.0.0.1',
            'port' => 6379,
            'password' => 'Xun166123',
            'select' => 1,
            'timeout' => 0,
            'persistent' => false,
        ],
    ],
    'failed' => [
        'type' => 'none',
        'table' => 'failed_jobs',
    ],
];

接下來添加隊列

/*
* 隊列任務
* @author zakeear <zakeear@86dede.com>
* @version v0.1.5
* @time 2019-06-10
*/
namespace app\queue\controller;
use think\Exception;
use think\facade\Db;
use think\facade\Queue;
class Host{
    /**
     * 添加隊列
     * @access public
     * @param int $subid 主機id
     * @param string $type 任務名
     * @param int $times 延時秒數
     * @throws \think\Exception
     */
    public function addTask(int $subid=0,string $type='server',int $times=0){
        $server=Db::name('server')->where(['subid'=>$subid])->find();
        if(!$server){
            exit;
        }
        switch($type){
            case 'server':
                $jobHandlerClassName='app\queue\job\Money@fire';
                $jobDataArr=['submit'=>time(),'doit'=>time()+$times,'subid'=>$server['subid'],'hostname'=>$server['hostname']];
                $jobQueueName="Money";
                break;
            case 'destroy':
                $jobHandlerClassName='app\queue\job\Destroy@fire';
                $jobDataArr=['submit'=>time(),'doit'=>time()+$times,'subid'=>$server['subid'],'hostname'=>$server['hostname']];
                $jobQueueName="Destroy";
                break;
            default:
                break;
        }
        if($times==0){
            $isPushed=Queue::push($jobHandlerClassName,$jobDataArr,$jobQueueName);
        }else{
            $isPushed=Queue::later($times,$jobHandlerClassName,$jobDataArr,$jobQueueName);
        }
    }
}

而後是消費者類

/*
* 主機扣費類
* @author zakeear <zakeear@86dede.com>
* @version v0.2.0
* @time 2019-06-13
*/
namespace app\queue\job;
use think\queue\Job;
use think\facade\Db;
class Money{
    public function fire(Job $job,$data){
        //job
        $isJobDone=$this->doJob($job,$data);
        $attempts=$job->attempts()+1;
        if($isJobDone){
            print('<info>['.date('Y-m-d H:i:s',time())."] 主機".$data['hostname']."扣費任務完成,任務銷燬</info>\n");
            $job->delete();
        }else{
            $release=strtotime(date('Y-m-d H:',time()).'00')+3599+date('i',$data['submit'])*60+date('s',$data['submit'])-time();
            print('<info>['.date('Y-m-d H:i:s',time())."] ".$release."秒後執行主機".$data['hostname']."第".$attempts."次扣費任務</info>\n");
            $job->release($release);
        }
    }
    private function doJob($job,$data){
        //job
        $attempts=$job->attempts();
        print('<info>['.date('Y-m-d H:i:s',time())."] 主機".$data['hostname']."第".$attempts."次扣費</info>\n");
        //主機
        $server=Db::name('server')->field('id,uid,subid,month,money,hostname,deduction')->where(['subid'=>$data['subid'],'status'=>2])->find();
        if(!$server){
            print('<info>['.date('Y-m-d H:i:s')."] 主機".$data['hostname']."已經不存在或者被刪除!"."\n");
            return true;
        }
        //日誌
        $logs=new \app\common\logic\Logs();
        //配置
        $this->config = Db::name('config')->field('rate,month,is_buy,vultr_api,vultr_keys,web_name,web_icon,time')->where(['status'=>1])->order('time','desc')->find();
        if($server['deduction']==$this->config['month']){
            //扣費
            $logs->database($server['uid'],5,'','主機【'.$server['hostname'].'】達到月付限額,本月再也不扣費',1,$server['subid']);
            //計數
            Db::name('server')->where(['subid'=>$data['subid']])->update(['deduction'=>0,'deduction_time'=>0]);
            //job
            $attempts=$attempts-1;
            print('<info>['.date('Y-m-d H:i:s')."] 主機".$data['hostname']."已經達到月付上限".$attempts."次\n");
            //隊列
            $job=new \app\queue\controller\Host();
            //刪除
            $job->addTask($data['subid'],'destroy',0);
            //建立
            $release=\app\Timer::nextMonth()[0]+date('i',$data['submit'])*60+date('s',$data['submit'])-time();//下月從新計費
            $job->addTask($data['subid'],'server',$release);
            //返回
            return true;
        }
        //用戶
        $user=Db::name('user')->field('id,money')->where(['id'=>$server['uid']])->find();
        if($user['money']<$server['money']){
            //日誌
            $logs->database($server['uid'],5,'','主機【'.$server['hostname'].'】不足於支付:【'.$server['money'].'】',1,$server['subid']);
            //刪除
            Db::name('server')->where(['subid'=>$data['subid']])->update(['status'=>5,'destroy'=>time()]);
            //日誌
            $logs->database($server['uid'],5,'','主機【'.$server['hostname'].'】刪除',1,$server['subid']);
            //隊列
            $job=new \app\queue\controller\Host();
            //刪除
            $job->addTask($data['subid'],'destroy',0);
            //job
            print('<info>['.date('Y-m-d H:i:s')."] 用戶餘額不足於支付".$user['money']."元\n");
            //返回
            return true;
        }
        //費用
        $money=new \app\common\logic\Money();
        //扣費
        $money->hostDec($server['uid'],1,$server['money'],1,$server['subid'],'主機【'.$server['hostname'].'】支付費用');
        //日誌
        $logs->database($server['uid'],5,'','主機【'.$server['hostname'].'】支付費用:【'.$server['money'].'】',1,$server['subid']);
        //計數
        Db::name('server')->where(['subid'=>$data['subid']])->inc('deduction',1)->update(['deduction_time'=>time()]);
    }
}

建立好後,文件目錄對應結構以下:

圖片描述

守護消費者進程

參考此文章

https://segmentfault.com/a/11...

或者使用寶塔的計劃任務

添加如下腳本

#檢查php Money 隊列腳本是否啓動
php_count=`ps -ef | grep Money | grep -v "grep" | wc -l`
if [ $php_count == 0 ];then
    echo '----php Money queue start'
    `sudo -H -u www bash -c 'nohup php /www/wwwroot/www.demo.com/think queue:listen --queue Money > /www/wwwroot/www.demo.com/logs/Money.txt 2>&1 &'`
else
    echo '----php Money queue ok'
fi

#檢查php DestroyQueue 隊列腳本是否啓動
php_count=`ps -ef | grep Destroy | grep -v "grep" | wc -l`
if [ $php_count == 0 ];then
    echo '----php Destroy queue start'
    `sudo -H -u www bash -c 'nohup php /www/wwwroot/www.demo.com/think queue:listen --queue Destroy > /www/wwwroot/www.demo.com/logs/Destroy.txt 2>&1 &'`
else
    echo '----php Destroy queue ok'
fi

如圖:

圖片描述

代碼解讀

think-queue 目前爲止還未實現subscribe功能,這裏利用了think-queue的延時隊列來實現定時任務,當消費者類裏的任務完成之後,不return true,使用延時拋回給隊列就好,該隊列會一直存在不會被刪除,也就變相的實現定時任務了。

不過到這裏會有一個疑問,如何準確告訴隊列須要延時多久?

代碼以下:

$release=strtotime(date('Y-m-d H:',time()).'00')+3599+date('i',$data['submit'])*60+date('s',$data['submit'])-time();
            print('<info>['.date('Y-m-d H:i:s',time())."] ".$release."秒後執行主機".$data['hostname']."第".$attempts."次扣費任務</info>\n");
            $job->release($release);

這裏就很關鍵了,須要你本身計算出來,假如一分鐘一次,按常理$job->release(60)就搞定了,可是忘記了消費者類運行自己是須要時間的,起碼幾百毫秒是要的。遇到任務多的時候,可能1-2秒才能完成,加入第一次任務在15:00:01開始消費任務,消費完成又花了1秒,消費完成後你再$job->release(60)那麼下次執行消費隊列就是15:01:02,那麼第三次執行就是15:01:03,依次類推,60次任務後,中間出現了有長達一分鐘沒有扣費的狀況,這對須要定時扣費的項目來講就是bug或者災難。這裏咱們經過動態計算來決定延時多少秒後,就解決了這個問題,常常生產環境長達2個月的觀察,偏差是先後2秒。這裏留個引子,若是控制到先後不超過1秒呢?假如這時候任務隊列太多,堆積了成千上百條隊列再排隊了之後,又該如何處理?下一期咱們可能會爲大家講解如何使用think-queue實現任務調度來打造一個支持高併發的訂單下單系統。

文章裏缺失的代碼部分,請前往https://github.com/zakeear/man查找或者自行結合業務進行修改。

think-queue 3.0和think-queue 2.0 變化

https://github.com/coolseven/...,thinkphp的隊列核心是本身編寫的,laravel的隊列核心依賴於symfony/process這個composer包。翻閱think-queue 3.0的源碼後發現

圖片描述正好契合了thinkphp6.0的理念,全面擁抱composer!由此也帶來了think-queue 3.0和think-queue 2.0最大的一個區別,think-queue 3.0須要註冊服務,think-queue 2.0不須要,這點差別會引起一個小編在使用過程當中遇到的極端問題,windows下安裝好的think-queue 3.0 到了liunx上,php think queue無效。若是有同類問題,解決把辦法是在liunx上安裝thinkphp6.0和think-queue 3.0後下載到windows下使用便可,這點習慣在windows下開發的小夥伴要注意。

另一點,使用過think-queue 2.0的同窗會發現,think-queue 3.0要想正常使用必須依賴於php的兩個內置函數,而這2個內置函數太對於敏感,運維通常會禁用,小編推薦的寶塔也會默認禁用掉它們,think-queue 3.0更換到symfony/process這個包之後,就再也不依賴這2個內置函數,從這點來講因此3.0要比2.0更加安全。

結語

https://www.kancloud.cn/think... ThinkPHP開發者週刊是Thinkphp生態的重要一環,流年已經獨自一人更新維護了1年多,爲廣大phper提供了一個學習和認識php圈子裏優秀的項目、書籍、開發者的渠道,目前該週刊已經轉由志願者維護,不遠的未來,將會交由社區維護。目前有好的文章、項目、書籍和案例,歡迎你們投稿。投稿地址:QQ羣:780179357

本教程實有倉促,文中若有遺漏和錯誤歡迎指正。本教程完整實例源碼已經託管到giehub:https://github.com/zakeear/man

相關文章
相關標籤/搜索