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

                ## 官網文檔 > thinkphp6文檔 > http://www.hmoore.net/manual/thinkphp6_0/1037479 > swoole文檔 > https://wiki.swoole.com/#/ > think-swoole文檔 > http://www.hmoore.net/manual/thinkphp6_0/1359700 ## 安裝 ~~~ composer require topthink/think-swoole ~~~ ## 命令行 ``` php think swoole [start|stop|reload|restart] ``` ## 服務啟動 當你在命令行`php think swoole`下執行完成之后就會啟動一個HTTP Server,可以直接訪問當前的應用 ~~~ 'server' => [ 'host' => env('SWOOLE_HOST', '0.0.0.0'), // 監聽地址 'port' => env('SWOOLE_PORT', 9501), // 監聽端口 'mode' => SWOOLE_PROCESS, // 運行模式 默認為SWOOLE_PROCESS 'sock_type' => SWOOLE_SOCK_TCP, // sock type 默認為SWOOLE_SOCK_TCP 'options' => [ // 服務啟動后,進程ID存放文件 'pid_file' => runtime_path() . 'swoole.pid', // swoole 的日志文件 'log_file' => runtime_path() . 'swoole.log', // 守護進程模式設置 true 后臺運行 'daemonize' => false, // 設置啟動的reactor線程數 'reactor_num' => swoole_cpu_num(), // 設置啟動的worker進程數 'worker_num' => swoole_cpu_num(), //配置Task進程的數量 'task_worker_num' => swoole_cpu_num(), //開啟靜態文件請求處理,需配合document_root 'enable_static_handler' => true, //靜態文件根目錄 'document_root' => root_path('public'), // 設置最大數據包尺寸,單位字節 'package_max_length' => 20 * 1024 * 1024, //配置發送輸出緩沖區內存尺寸 'buffer_output_size' => 10 * 1024 * 1024, //設置客戶端連接最大允許占用的內存數量 'socket_buffer_size' => 128 * 1024 * 1024, ], ], ~~~ ## 熱更新 swoole服務器運行過程中php文件是常駐內存運行,這樣就可以避免重復的讀取磁盤,重復的解釋編譯php,以便達到最高的性能,所以修改代碼需要重啟服務 think-swoole擴展提供熱更新功能,在檢測相關文件有更新會自動重啟,不在需要手動完成重啟,方便開發調試 生產環境下不建議開始文件監控,性能損耗,正常情況下你所修改的文件需要確認無誤才能進行更新部署 `.env`里面設置`APP_DEBUG = true`會默認開啟熱更新 ~~~ 'hot_update' => [ 'enable' => env('APP_DEBUG', false), 'name' => ['*.php'], 'include' => [app_path()], 'exclude' => [], ], ~~~ 參數說明 | 參數 | 說明 | | ------- | ------------------------ | | enable | 是否開啟熱更新 | | name | 監聽哪些類型的文件變動 | | include | 監聽哪些目錄下的文件變動 | | exclude | 排除目錄 | ## websocket 先來一個官方的例子 ~~~ $server = new Swoole\WebSocket\Server("0.0.0.0", 9501); $server->on('open', function (Swoole\WebSocket\Server $server, $request) { echo "server: handshake success with fd{$request->fd}\n"; }); $server->on('message', function (Swoole\WebSocket\Server $server, $frame) { echo "receive from {$frame->fd}:{$frame->data}\n"; $server->push($frame->fd, "this is server"); }); $server->on('close', function ($ser, $fd) { echo "client {$fd} closed\n"; }); $server->start(); ~~~ 開啟think-swoole的websocket功能 `\config\swoole.php` ~~~ 'websocket' => [ 'enable' => true, ], ~~~ 創建三個事件 ~~~ php think make:listener SwWsConnect php think make:listener SwWsClose php think make:listener SwWsMessage ~~~ 然后將這三個事件寫到到事件監聽中,分別有以下2中文件可以修改方式,注意二選一 thinkphp6自帶的事件綁定`app\event.php` ~~~ 'listen' => [ ........ // 監聽鏈接 'swoole.websocket.Connect' => [ \app\listener\SwWsConnect::class ], //關閉連接 'swoole.websocket.Close' => [ \app\listener\SwWsClose::class ], //發送消息場景 'swoole.websocket.Message' => [ \app\listener\SwWsMessage::class ] ], ~~~ think-swoole事件綁定`config\swoole.php` ~~~ 'listen' => [ 'connect'=>\app\listener\SwWsConnect::class, 'close'=>\app\listener\SwWsClose::class, 'message'=> \app\listener\SwWsMessage::class ], ~~~ > 怎么選擇是保存在`config\swoole.php`還是`app\event.php`配置中呢? > > 首先我們 我們確定一下我們這個項目中存在有幾個實時通訊, > > 如果只是存在一個實時通訊 個人建議 保存在`config\swoole.php` > > 如果是存在多個實時通訊,就保存在`app\event.php` > > key值 必須是`swoole.websocket.事件名稱` 例如 `swoole.websocket.Message` 開始寫事件中中方法 連接事件`app\listener\SwWsConnect.php` ~~~ public function handle($event, \think\swoole\websocket $ws) { // 獲取當前發送者的fd $fd = $ws->getSender(); echo "server: handshake success with fd{$fd}\n"; } ~~~ 關閉事件`app\listener\SwWsClose.php` ~~~ public function handle($event, \think\swoole\websocket $ws) { $fd = $ws->getSender(); echo "client {$fd} closed\n"; } ~~~ message事件`app\listener\SwWsMessage.php` ~~~ public function handle($event, \think\swoole\websocket $ws) { $fd = $ws->getSender(); $data = json_encode($event); echo "receive from {$fd}:{$data}\n"; $ws->emit("this is server", $fd); } ~~~ 啟動`php think swoole`進行測試 think-swoole中的websocket方法總結 ~~~ //給自己發消息 $ws->emit("this is server", $ws->getSender()); //給指定一個fd發消息 $ws->to($to)->emit("messagecallback",$data); //給指定多個人發消息 $ws->to([1,2,3])->emit("messagecallback",$data); //發送給所有的(不包含自己) $ws->broadcast()->emit("messagecallback",$data); //模擬formfd 給tofd 發送消息 $ws->setSender($formfd)->to($tofd)->emit("messagecallback",$data); ~~~ > 注意:在多個實時通訊場景下使用 `emit` > > 第一個參數傳入 傳入 事件名稱callback 例如 `messagecallback` 如果你發現你think-swoole中有些沒有swoole中的方法可以這么干 ~~~ $sw = app('swoole.server'); $sw = app("think\swoole\Manager")->getServer(); //以上二選一 $es = $sw->isEstablished($fd); //檢查連接是否為有效的WebSocket客戶端連接 var_dump($es); ~~~ ## 聊天室room實現 前端文件參考 `html\room.html` 或 `html\room-socket-io.html` ~~~ php think make:listener SwRoomJoin php think make:listener SwRoomLeave php think make:listener SwRoomMessage ~~~ 事件綁定 ~~~ // 加入房間 'swoole.websocket.RoomJoin' => [ \app\listener\SwRoomJoin::class ], // 離開房間 'swoole.websocket.Roomleave' => [ \app\listener\SwRoomLeave::class ], // 在房間發消息 'swoole.websocket.RoomMessage' => [ \app\listener\SwRoomMessage::class ] ~~~ 加入房間邏輯 ~~~ public function handle($event, \think\swoole\websocket $ws, \think\swoole\websocket\room $room) { $fd = $ws->getSender(); //客戶端假如定的room $roomid = $event['room']; //獲取指定房間下有哪些客戶端 $roomfds = $room->getClients($roomid); // 判斷這個房間有沒有自己 如果有自己就不需要再次發送通知 if (in_array($fd, $roomfds)) { $ws->to($roomfds)->emit("roomjoincallback", "房間{$roomid}已加入"); return; } //加入房間 $ws->join($roomid); $ws->to($roomfds)->emit("roomjoincallback", "{$fd}加入房間{$roomid}成功"); } ~~~ 離開房間邏輯 ~~~ public function handle($event, \think\swoole\websocket $ws, \think\swoole\websocket\Room $room) { $roomid = $event['room']; $fd = $ws->getSender(); $roomfds = $room->getClients($roomid); if (!in_array($fd, $roomfds)) { $ws->emit("roomleavecallback", "{$fd}不在{$roomid}房間內,怎么離開~"); return; } //離開房間 $ws->leave($roomid); //獲取當前客戶端加入了哪些客戶端 $rooms = $room->getRooms($fd); $ws->to($roomfds)->emit("roomleavecallback", "{$fd}已離開了~~"); } ~~~ 在房間發布聊天邏輯 ~~~ public function handle($event, \think\swoole\websocket $ws, \think\swoole\websocket\room $room) { // $roomid = $event['room']; $text = $event['text']; $fd = $ws->getSender(); $roomfds = $room->getClients($roomid); if (!in_array($fd, $roomfds)) { $ws->emit("roommessagecallback", "{$fd}不在{$roomid}房間內,無法進入發布聊天~"); return; } $ws->to($roomfds)->emit("roommessagecallback", $text); } ~~~ ## 事件訂閱 ~~~ php think make:listener SwSubscribe ~~~ app\listener\SwSubscribe.php ~~~ <?php declare (strict_types = 1); namespace app\listener; class SwSubscribe { protected $ws = null; // public function __construct() // { // $this->ws = app('think\swoole\Websocket'); // } public function __construct(\think\Container $c) { $this->ws = $c->make(\think\swoole\Websocket::class); } public function onConnect() { $fd = $this->ws->getSender(); echo "server: handshake success with fd{$fd}\n"; } public function onClose() { $fd = $this->ws->getSender(); echo "client {$fd} closed\n"; } public function onMessage($event) { $fd = $this->ws->getSender(); var_dump($event); echo "server: handshake success with fd{$fd}\n"; $this->ws->emit("this is server", $fd); } } ~~~ > 有點類似 將原生的swoole代碼改成面向對象代碼,生效方法 `config\swoole.php`中在`subscribe` 加入`\app\listener\SwSubscribe::class` > > ~~~ > 'subscribe' => [ > \app\listener\SwSubscribe::class > ], > ~~~ > > 在`app\event.php`文件中的 `swoole.websocket.Connect` 相當于 `app\listener\SwSubscribe.php`文件中的`onConnect`函數。如果同時存在的存在的話,就會向客戶端發送2次以上的消息 ## Task任務投遞 https://wiki.swoole.com/#/start/start_task 生成事件 ~~~ php think make:listener SwSendEmailTask ~~~ 編寫發送郵件方法`app\listener\SwSendEmailTask.php` ~~~ public function handle($event) { var_dump($event); // echo "開發發送郵件".time(); sleep(3); echo "結束發送郵件".time(); } ~~~ 注冊事件`app\event.php` ~~~ 'swoole.task'=>[ \app\listener\SwSendEmailTask::class ], ~~~ 在控制器中投遞任務 ~~~ public function doRegister() { $server = app('swoole.server'); $server->task(\app\listener\SwSendEmailTask::class); return "注冊成功"; } public function doRegister(\think\swoole\Manager $manager) { $server = $manager->getServer(); $server->task(\app\listener\SwSendEmailTask::class); return "注冊成功"; } public function doRegister(\Swoole\Server $server) { $server->task(\app\listener\SwSendEmailTask::class); return "注冊成功"; } ~~~ > 三種獲取`\Swoole\Server`,任意選其一 在swoole中還有一個事件叫`finish`,它的作用就是把異步任務的結果返回,在think-swool是這么處理的 定義一個發送郵件異步任務處理結果的事件 ~~~ php think make:listener SwSendEmailFinish ~~~ 注冊事件`app\event.php` ~~~ 'swoole.finish'=>[ \app\listener\SwSendEmailFinish::class ], ~~~ 在task任務中調用 ~~~ public function handle($event) { var_dump($event); // echo "開發發送郵件".time(); sleep(3); echo "結束發送郵件".time(); $event->finish(\app\listener\SwSendEmailFinish::class); } ~~~ ## 高性能共享內存 Table https://wiki.swoole.com/#/memory/table 先定結構在進行操作數據(原生swoole操作) ~~~ $table = new Swoole\Table(1024); //創建表 $table->column("id", Swoole\Table::TYPE_INT); $table->column("name", Swoole\Table::TYPE_STRING); $table->column("money", Swoole\Table::TYPE_FLOAT); $table->create(); //添加數據 $table->set("zq", [ 'id' => 1, 'name' => "zhiqiang", 'money' => 100, ]); //獲取一行數據 $table->get("zq"); // 修改數據 // 字段遞增 $table->incr("zq","money",2); //遞減 $table->decr("zq","money",2); // 返回 table 中存在的條目數。 $table->count(); //遍歷table中的數據 foreach($table as $item){ var_dump($item); } ~~~ think-swoole中的操作 先對table表結構進行初始化`config\swoole.php` ~~~ 'tables' => [ 'user'=>[ 'size'=>1024, 'columns'=>[ [ 'name'=>'id', 'type'=>\Swoole\Table::TYPE_INT ], [ 'name'=>'name', 'type'=>\Swoole\Table::TYPE_STRING, 'size'=>32 ], [ 'name'=>'money', 'type'=>\Swoole\Table::TYPE_FLOAT ], ], ], ], ~~~ 操作數據 ~~~ $table = app('swoole.table.user'); $table->set("zq", [ 'id' => 1, 'name' => "zhiqiang", 'money' => 100 ]); //獲取一行數據 $table->get("zq"); // 修改數據 // 字段遞增 $table->incr("zq", "money", 2); //遞減 $table->decr("zq", "money", 2); // 返回 table 中存在的條目數。 $table->count(); //遍歷table中的數據 foreach ($table as $item) { var_dump($item); } // 檢查 table 中是否存在某一個 key。 $table->exist('zq'); //獲取實際占用內存尺寸,單位字節 $table->momorySize(); ~~~ ## RPC RPC(Remote Procedure Call):遠程過程調用,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的思想。 詳細介紹:https://developer.51cto.com/art/201906/597963.htm - 解決分布式系統中,服務之間的調用問題。 - 遠程調用時,要能夠像本地調用一樣方便,讓調用者感知不到遠程調用的邏輯。 - 節點角色說明: - Server: 暴露服務的服務提供方 - Client: 調用遠程服務的服務消費方 - Registry: 服務注冊與發現的注冊中心 think-swoole實現RPC功能 ### 服務器端 #### 接口定義`app/rpc/interfaces/UserInterface.php` ~~~ <?php namespace app\rpc\interfaces; interface UserInterface { public function create(); public function find(int $id); } ~~~ #### 實現接口`app/rpc/services/UserService.php` ~~~ <?php namespace app\rpc\services; use app\rpc\interfaces\UserInterface; class UserService implements UserInterface { public function create() { // TODO: Implement create() method. return "service create success"; } public function find(int $id) { // TODO: Implement find() method. return $id. "查詢數據遍歷"; } } ~~~ #### 注冊rpc服務`config/swoole.php` ~~~ 'rpc' => [ 'server' => [ //開啟rpc服務 'enable' => true, //rpc端口 'port' => 9000, 'services' => [ //注冊服務 \app\rpc\services\UserService::class ], ], // 如果填寫也是可以調用其他服務端 'client' => [ ], ], ~~~ 啟動服務端 ~~~ php think swoole start / php think swoole:rpc ~~~ ### 客戶端 ~~~ 'rpc' => [ 'server' => [ ], 'client' => [ 'tp6'=>[ //服務端的ip地址 'host'=>'127.0.0.1', //服務端對應的端口 'port'=>'9000' ] // 更多服務端 ], ], ~~~ 運行`php think rpc:interface`生成RPC接口文件`app\rpc.php` ~~~ <?php /** * This file is auto-generated. */ declare(strict_types=1); namespace rpc\contract\tp6; interface UserInterface { public function create(); public function find(int $id); } return ['tp6' => ['rpc\contract\tp6\UserInterface']]; ~~~ 在控制器調用 ~~~ public function index(\rpc\contract\tp6\UserInterface $user) { // $user->find(1); // $user->create(); } ~~~ 殺死所有指定名稱進程 ~~~ ps -ef | grep swoole | grep -v grep | awk '{print $2}' | xargs kill -9 ~~~
                  <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>

                              哎呀哎呀视频在线观看