<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                _計算機科學中的任何問題都可以用另外的間接層解決,但是這通常會引發另一個問題。 -- David Wheeler_ ## 2.15.1 新型計劃任務回顧 在 [[1.31]-新型計劃任務:以接口形式實現的計劃任務](/wikis/%5B1.31%5D-%E6%96%B0%E5%9E%8B%E8%AE%A1%E5%88%92%E4%BB%BB%E5%8A%A1%EF%BC%9A%E4%BB%A5%E6%8E%A5%E5%8F%A3%E5%BD%A2%E5%BC%8F%E5%AE%9E%E7%8E%B0%E7%9A%84%E8%AE%A1%E5%88%92%E4%BB%BB%E5%8A%A1.html) 一章中,我們討論了PhalApi中對計劃任務的設計和底層實現。 但對于很多應用,很多項目,或者很多同學來說,仍然比較廣泛,不能直接使用。 這一章則專門為此而進行演進,并提供最終可用的計劃任務調度,同時我們也會闡明如何進行擴展定制。 也就是說,這一章將提供Task擴展類庫的統一調度方式,以便在啟動crontab任務后,可以通過數據庫簡單配置,即可執行各種任務。 ## 2.15.2 最終調度的方式:crontab 出于對業務的考慮,我們首先需要明確此crontab調度方式所支持的功能,它應該包括但不限于: + 1、通過簡單的數據庫配置,即可啟動一個新的任務 + 2、具備循環調度的能力,并能初步防止并發調度 + 3、可以對異常的任務進行修復 + 4、優先執行太遠未執行的任務 + 5、支持本地和遠程兩種調度方式、三種MQ類型,以及擴展的能力 ## 2.15.3 核心時序圖與分層 在原來的時序圖基礎上,我們可以進行演進的設計,追加了統一的調度后如下所示: ![a pic](http://webtools.qiniudn.com/task_6.jpg) 通過上面詳細的時序圖,我們可以發現里面的設計是出于這樣的分層考慮: 序號|層|關鍵操作|說明|如何使用 ---|---|---|---|--- 1|啟動腳本|crontab.php|操作crontab執行的腳本|客戶端可以進行必要的初始化工作 2|進程級|Task_Progress::run()|根據進程配置的數據庫表,進行循環調度|不需要改動,直接使用 3|觸發器|Task_Trigger::fire()|進行計劃任務調度的上下文環境,用于指定runner和mq類型|客戶端也可進行定制擴展,進行必要的操作 4|MQ消費與調度|Task_MQ::pop()和Task_Runner::go()|不斷消費MQ隊列,并依次進行調度|不需要改動,直接使用,也可擴展 5|計劃任務服務|PhalApi_Api::doSth()|執行計劃任務服務|由客戶端按接口形式實現 雖然上面的層級,初看起來有點多,但我們再次驗證了計算機那個偉大的定論:計算機的任何問題都可以通過一個中間層來解決。 由此看出,上面的層級其實相當于: ``` 客戶端初始化 --> 直接使用 --> 自由組合與操作 --> 直接使用 --> 任務服務實現 ``` ## 2.16.4 進程配置的數據庫表設計 ```javascript CREATE TABLE `phalapi_task_progress` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `title` varchar(200) DEFAULT '' COMMENT '任務標題', `trigger_class` varchar(50) DEFAULT '' COMMENT '觸發器類名', `fire_params` varchar(255) DEFAULT '' COMMENT '需要傳遞的參數,格式自定', `interval_time` int(11) DEFAULT '0' COMMENT '執行間隔,單位:秒', `enable` tinyint(1) DEFAULT '1' COMMENT '是否啟動,1啟動,0禁止', `result` varchar(255) DEFAULT '' COMMENT '運行的結果,以json格式保存', `state` tinyint(1) DEFAULT '0' COMMENT '進程狀態,0空閑,1運行中,-1異常退出', `last_fire_time` int(11) DEFAULT '0' COMMENT '上一次運行時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; ``` 對此表的關鍵字段說明如下: 字段|說明|示例 ---|---|--- trigger_class|觸發器的類名|須實現Task_Progress_Trigger::fire($params)接口 fire_params|觸發器的參數|加傳給Task_Progress_Trigger::fire()函數的參數,格式為:service&MQ類名&runner類名 interval_time|執行間隔|單位為秒 enable|是否啟動|此字段禁止時,將不再執行 state|進程狀態|當此狀態一直為異常或者運行且超過1天時,系統會進行修復,即重置為空閑狀態 其中,對于fire_params參數,MQ類名和runner類名可選,以下是一些示例: ```javascript //示例1:完整的配置 //fire_params=Task_Demo.DoSth&Task_MQ_DB&Task_Runner_Local $mq = new Task_MQ_DB(); $runner = new Task_Runner_Local($mq); $runner->go('Task_Demo.DoSth'); //示例2:使用默認的Runner //fire_params=Task_Demo.DoSth&Task_MQ_DB $mq = new Task_MQ_DB(); $runner = new Task_Runner_Local($mq); //默認使用本地Runner $runner->go('Task_Demo.DoSth'); //示例3:使用默認的MQ和默認的Runner //fire_params=Task_Demo.DoSth $mq = new Task_MQ_Redis(); //默認使用redis的MQ $runner = new Task_Runner_Local($mq); //默認使用本地Runner $runner->go('Task_Demo.DoSth'); //示例4:使用自定義的MQ和Runner //fire_params=Task_Demo.DoSth&My_MQ&My_Runner class My_MQ implements Task_MQ { // ... } class My_Runner extends Task_Runner { // ... } $mq = new My_MQ(); $runner = new My_Runner($mq); $runner->go('Task_Demo.DoSth'); ``` ## 2.15.5 運行效果 最終的效果就是,我們通過這樣兩行簡單的代碼,即可實現一系列復雜的任務調度: ```javascript $progress = new Task_Progress(); $progress->run(); ``` 讓我們來看下這樣設計的運行效果吧!看下這兩行代碼背后所產生的魔力。 首先,我們先添加兩條計劃任務: ```javascript INSERT INTO `phalapi_task_progress` VALUES ('1', 'test demo', 'Task_Progress_Trigger_Common', 'Task_Demo.DoSth&Task_MQ_File&Task_Runner_Local', '300', '1', '', '0', '0'); INSERT INTO `phalapi_task_progress` VALUES ('2', 'test ok', 'Task_Progress_Trigger_Common', 'Default.Index&Task_MQ_DB&Task_Runner_Local', '100', '1', '', '0', '0'); ``` 然后,偽造一些MQ: ```javascript INSERT INTO `phalapi_task_mq_0` VALUES ('8', 'Default.Index', '', '0', ''); ``` 最后,生成單元測試: ```javascript <?php class PhpUnderControl_TaskProgress_Test extends PHPUnit_Framework_TestCase { public $taskProgress; protected function setUp() { parent::setUp(); $this->taskProgress = new Task_Progress(); } /** * @group testRun */ public function testRun() { $rs = $this->taskProgress->run(); } } ``` 并執行之: ```javascript $ phpunit ./Task_Progress_Test.php [1 - 0.06666s]SELECT id, title FROM phalapi_task_progress WHERE (state != ?) AND (last_fire_time < ?) AND (enable = ?) ORDER BY last_fire_time ASC; -- 0, 1431965153, 1<br> [2 - 0.07002s]SELECT id, title, trigger_class, fire_params FROM phalapi_task_progress WHERE (state = 0) AND (interval_time + last_fire_time < ?) AND (enable = ?); -- 1432051553, 1<br> [3 - 0.06549s]SELECT enable, state FROM phalapi_task_progress WHERE (id = '1');<br> [4 - 0.07432s]UPDATE phalapi_task_progress SET state = 1 WHERE (id = '1');<br> [5 - 0.06469s]UPDATE phalapi_task_progress SET result = '{\"total\":0,\"fail\":0}', state = 0, last_fire_time = 1432051553 WHERE (id = '1');<br> [6 - 0.06746s]SELECT enable, state FROM phalapi_task_progress WHERE (id = '2');<br> [7 - 0.07043s]UPDATE phalapi_task_progress SET state = 1 WHERE (id = '2');<br> [8 - 0.06673s]SELECT id, params FROM phalapi_task_mq_0 WHERE (service = 'Default.Index') ORDER BY id ASC LIMIT 0,10;<br> [9 - 0.48185s]DELETE FROM phalapi_task_mq_0 WHERE (id IN ('8'));<br> [10 - 0.06514s]SELECT id, params FROM phalapi_task_mq_0 WHERE (service = 'Default.Index') ORDER BY id ASC LIMIT 0,10;<br> [11 - 0.50694s]UPDATE phalapi_task_progress SET result = '{\"total\":1,\"fail\":0}', state = 0, last_fire_time = 1432051553 WHERE (id = '2');<br> Time: 1.98 seconds, Memory: 6.50Mb OK (1 test, 0 assertions) ``` 查看對比一下數據庫,目前發現運行良好! 提交代碼,保存文檔,收工睡覺! ## 2.15.6 演進的樂趣 得益于前期良好的設計以及底層支持,我們發現,在提供這樣一種統一的調度方式是非常方便的。 不僅如此,如果你明白了其中的設計,需要進行定制和擴展也是非常方便的。也就是說,我們不僅提供了一種具體實際可用的方式,也提供了廣闊自由的擴展空間。具體與抽象,兩者仍可得。 然而,這一切不僅依賴于良好的設計,還依賴于測試驅動開發下的浮現式設計。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看