<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                > 環境說明: 系統:Ubuntu14.04 (安裝教程包括CentOS6.5) > PHP版本:PHP-5.5.10 > swoole版本:1.7.7-stable ## **1.Timer定時器** 在實際應用中,往往會遇到需要每隔一段時間重復做一件事,比如心跳檢測、訂閱消息、數據庫備份等工作。通常,我們會借助PHP的time()以及相關函數自己實現一個定時器,或者使用crontab工具來實現。但是,自定義的定時器容易出錯,而使用crontab則需要編寫額外的腳本文件,無論是遷移還是調試都比較麻煩。 因此,Swoole提供了一個內置的Timer定時器功能,通過函數[addtimer](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/03.swoole_server%E5%87%BD%E6%95%B0%E5%88%97%E8%A1%A8.md#swoole_serveraddtimer)即可在Swoole中添加一個定時器,該定時器會在建立之后,按照預先設定好的時間間隔,每到對應的時間就會調用一次回調函數[onTimer](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/02.%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0.md#8ontimer)通知Server。 簡單示例如下: ~~~ $this->serv->on('Timer', array($this, 'onTimer')); public function onWorkerStart( $serv , $worker_id) { // 在Worker進程開啟時綁定定時器 // 只有當worker_id為0時才添加定時器,避免重復添加 if( $worker_id == 0 ) { $serv->addtimer(500); $serv->addtimer(1000); $serv->addtimer(1500); } } public function onTimer($serv, $interval) { switch( $interval ) { case 500: { // echo "Do Thing A at interval 500\n"; break; } case 1000:{ echo "Do Thing B at interval 1000\n"; break; } case 1500:{ echo "Do Thing C at interval 1500\n"; break; } } } ~~~ 可以看到,在[onWorkerStart](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/02.%E4%BA%8B%E4%BB%B6%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0.md#3onworkerstart)回調函數中,通過addtimer添加了三個定時器,時間間隔分別為500、1000、1500。而在onTimer回調中,正好通過間隔的不同來區分不同的定時器回調,從而執行不同的操作。 需要注意的是,在上述示例中,當1000ms的定時器被觸發時,500ms的定時器同樣會被觸發,但是不能保證會在1000ms定時器前觸發還是后觸發,因此需要注意,定時器中的操作不能依賴其他定時器的執行結果。 [點此查看完整示例](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/03/swoole_timer_server.php) (PS:在Swoole-1.7.7版本,新提供了一個[after](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/03.swoole_server%E5%87%BD%E6%95%B0%E5%88%97%E8%A1%A8.md#swoole_serverafter)函數, 這個功能的用法會在以后的教程中給出。) ## **2.心跳檢測** 上文提到過,使用Timer定時器功能可以實現發送心跳包的功能。事實上,Swoole已經內置了心跳檢測功能,能自動close掉長時間沒有數據來往的連接。而開啟心跳檢測功能,只需要設置[heartbeat_check_interval](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/01.%E9%85%8D%E7%BD%AE%E9%80%89%E9%A1%B9.md#11heartbeat_check_interval)和[heartbeat_idle_time](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/01.%E9%85%8D%E7%BD%AE%E9%80%89%E9%A1%B9.md#12heartbeat_idle_time)即可。如下: ~~~ $this->serv->set( array( 'heartbeat_check_interval' => 60, 'heartbeat_idle_time' => 600, ) ); ~~~ 其中heartbeat_idle_time的默認值是heartbeat_check_interval的兩倍。 在設置這兩個選項后,swoole會在內部啟動一個線程,每隔heartbeat_check_interval秒后遍歷一次全部連接,檢查最近一次發送數據的時間和當前時間的差,如果這個差值大于heartbeat_idle_time,則會強制關閉這個連接,并通過回調onClose通知Server進程。?[點此查看完整示例](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/03/swoole_heartbeat_server.php)?**小技巧**: 結合之前的Timer功能,如果我們想維持連接,就設置一個略小于如果這個差值大于heartbeat_idle_time的定時器,在定時器內向所有連接發送一個心跳包。如果收到心跳回應,則判斷連接正常,如果沒有收到,則關閉這個連接或者再次嘗試發送。 ## **3.Task進階:MySQL連接池** 上一章中我簡單講解了如何開啟和使用Task功能。這一節,我將提供一個Task的高級用法。 在PHP中,訪問MySQL數據庫往往是性能提升的瓶頸。而MySQL連接池我想大家都不陌生,這是一個很好的提升數據庫訪問性能的方式。傳統的MySQL連接池,是預先申請一定數量的連接,每一個新的請求都會占用其中一個連接,請求結束后再將連接放回池中,如果所有連接都被占用,新來的連接則會進入等待狀態。 知道了MySQL連接池的實現原理,那我們來看如何使用Swoole實現一個連接池。 首先,Swoole允許開啟一定量的Task Worker進程,我們可以讓每個進程都擁有一個MySQL連接,并保持這個連接,這樣,我們就創建了一個連接池。 其次,設置swoole的[dispatch_mode](https://github.com/LinkedDestiny/swoole-doc/blob/master/doc/01.%E9%85%8D%E7%BD%AE%E9%80%89%E9%A1%B9.md#5dispatch_mode)為搶占模式(主進程會根據Worker的忙閑狀態選擇投遞,只會投遞給處于閑置狀態的Worker)。這樣,每個task都會被投遞給閑置的Task Worker。這樣,我們保證了每個新的task都會被閑置的Task Worker處理,如果全部Task Worker都被占用,則會進入等待隊列。 下面直接上關鍵代碼: ~~~ public function onWorkerStart( $serv , $worker_id) { echo "onWorkerStart\n"; // 判定是否為Task Worker進程 if( $worker_id >= $serv->setting['worker_num'] ) { $this->pdo = new PDO( "mysql:host=localhost;port=3306;dbname=Test", "root", "123456", array( PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8';", PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => true ) ); } } ~~~ 首先,在每個Task Worker進程中,創建一個MySQL連接。這里我選用了PDO擴展。 ~~~ public function onReceive( swoole_server $serv, $fd, $from_id, $data ) { $sql = array( 'sql'=>'select * from Test where pid > ?', 'param' => array( 0 ), 'fd' => $fd ); $serv->task( json_encode($sql) ); } ~~~ 其次,在需要的時候,通過[task](https://github.com/LinkedDestiny/swoole-doc/blob/master)函數投遞一個任務(也就是發起一次SQL請求) ~~~ public function onTask($serv,$task_id,$from_id, $data) { $sql = json_decode( $data , true ); $statement = $this->pdo->prepare($sql['sql']); $statement->execute($sql['param']); $result = $statement->fetchAll(PDO::FETCH_ASSOC); $serv->send( $sql['fd'],json_encode($result)); return true; } ~~~ 最后,在onTask回調中,根據請求過來的SQL語句以及相應的參數,發起一次MySQL請求,并將獲取到的結果通過send發送給客戶端(或者通過return返回給Worker進程)。而且,這樣的一次MySQL請求還不會阻塞Worker進程,Worker進程可以繼續處理其他的邏輯。 可以看到,簡單十幾行代碼,就實現了一個高效的異步MySQL連接池。 通過測試,單個客戶端一共發起1W次select請求,共耗時9s; 1W次insert請求,共耗時21s。 (客戶端會在每次收到前一個請求的結果后才會發起下一次請求,而不是并發)。 [點此查看完整服務端代碼](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/03/swoole_mysql_pool_server.php) [點此查看完整客戶端代碼](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/03/swoole_mysql_pool_client.php) ## **4.Task實戰:yii中應用task** 在YII框架中結合了swoole 的task 做了異步處理。 本例中 主要用到 1、protected/commands/ServerCommand.php 用來做server。 2、protected/event/下的文件 這里是在異步中的具體實現。 客戶端調用參照 TestController ~~~ <?php class TestController extends Controller{ public function actionTT(){ $message['uid'] = 2; $message['email'] = '83212019@qq.com'; $message['title'] = '接口報警郵件'; $message['contents'] = "'EmailEvent'接口請求過程出錯! 錯誤信息如下:err_no:'00000' err_msg:'測試隊列' 請求參數為:'[]'"; $message['type'] = 2; $data['param'] = $message; $data['class'] = 'Email'; $client = new EventClient(); $data = $client->send($data); } } ?> ~~~ 有個task表是用來記錄異步任務的。如果失敗重試3次。sql在protected/data/sql.sql里。 [點此查看完整客戶端代碼](https://github.com/LinkedDestiny/swoole-doc/blob/master/src/03/swoole_mysql_pool_client.php)
                  <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>

                              哎呀哎呀视频在线观看