我們都知道 HTTP 是一種協議,允許 WEB 伺服器和瀏覽器通過互聯網進行發送和接受數據。想對 HTTP 進行詳細的瞭解,可以找下其他文章,這篇文章不多做介紹。我們在網上能看到的界面,圖片,動畫,音頻,視頻 等,都有依賴這個協議的。在做 WEB 系統的時候,都使用過 IIS、Apache、Ngin ...
我們都知道 HTTP 是一種協議,允許 WEB 伺服器和瀏覽器通過互聯網進行發送和接受數據。
想對 HTTP 進行詳細的瞭解,可以找下其他文章,這篇文章不多做介紹。
我們在網上能看到的界面,圖片,動畫,音頻,視頻 等,都有依賴這個協議的。
在做 WEB 系統的時候,都使用過 IIS、Apache、Nginx 吧,我們利用 Swoole 也可以 簡單的實現一個 WEB 伺服器。
主要使用了 HTTP 的兩大對象:Request 請求對象、Response 響應對象。
Request,包括 GET、POST、COOKIE、Header等。
Response,包括 狀態、響應體、跳轉、發送文件等。
不多說,先分享兩個程式:
一、實現一個基礎的 Demo:“你好,Swoole.”
二、實現一個簡單的 路由控制
本地版本:
PHP 7.2.6
Swoole 4.3.1
代碼
一、Demo:“你好,Swoole.”
示例效果:
備註:IP 地址是我的虛擬機。
示例代碼:
<?php class Server { private $serv; public function __construct() { $this->serv = new swoole_http_server("0.0.0.0", 9502); $this->serv->set([ 'worker_num' => 2, //開啟2個worker進程 'max_request' => 4, //每個worker進程 max_request設置為4次 'daemonize' => false, //守護進程(true/false) ]); $this->serv->on('Start', [$this, 'onStart']); $this->serv->on('WorkerStart', [$this, 'onWorkStart']); $this->serv->on('ManagerStart', [$this, 'onManagerStart']); $this->serv->on("Request", [$this, 'onRequest']); $this->serv->start(); } public function onStart($serv) { echo "#### onStart ####".PHP_EOL; echo "SWOOLE ".SWOOLE_VERSION . " 服務已啟動".PHP_EOL; echo "master_pid: {$serv->master_pid}".PHP_EOL; echo "manager_pid: {$serv->manager_pid}".PHP_EOL; echo "########".PHP_EOL.PHP_EOL; } public function onManagerStart($serv) { echo "#### onManagerStart ####".PHP_EOL.PHP_EOL; } public function onWorkStart($serv, $worker_id) { echo "#### onWorkStart ####".PHP_EOL.PHP_EOL; } public function onRequest($request, $response) { $response->header("Content-Type", "text/html; charset=utf-8"); $html = "<h1>你好 Swoole.</h1>"; $response->end($html); } } $server = new Server();
這裡我還準備了一分學習圖和資料,如下:
鏈接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取碼:x2p5
免費分享,但是X度限制嚴重,如若鏈接失效點擊鏈接或搜索加群 群號518475424。
二、路由控制
示例效果:
目錄結構:
├─ swoole_http -- 代碼根目錄
│ ├─ server.php
│ ├─ controller
│ ├── Index.php
│ ├── Login.php
示例代碼:
server.php <?php class Server { private $serv; public function __construct() { $this->serv = new swoole_http_server("0.0.0.0", 9501); $this->serv->set([ 'worker_num' => 2, //開啟2個worker進程 'max_request' => 4, //每個worker進程 max_request設置為4次 'document_root' => '', 'enable_static_handler' => true, 'daemonize' => false, //守護進程(true/false) ]); $this->serv->on('Start', [$this, 'onStart']); $this->serv->on('WorkerStart', [$this, 'onWorkStart']); $this->serv->on('ManagerStart', [$this, 'onManagerStart']); $this->serv->on("Request", [$this, 'onRequest']); $this->serv->start(); } public function onStart($serv) { echo "#### onStart ####".PHP_EOL; swoole_set_process_name('swoole_process_server_master'); echo "SWOOLE ".SWOOLE_VERSION . " 服務已啟動".PHP_EOL; echo "master_pid: {$serv->master_pid}".PHP_EOL; echo "manager_pid: {$serv->manager_pid}".PHP_EOL; echo "########".PHP_EOL.PHP_EOL; } public function onManagerStart($serv) { echo "#### onManagerStart ####".PHP_EOL.PHP_EOL; swoole_set_process_name('swoole_process_server_manager'); } public function onWorkStart($serv, $worker_id) { echo "#### onWorkStart ####".PHP_EOL.PHP_EOL; swoole_set_process_name('swoole_process_server_worker'); spl_autoload_register(function ($className) { $classPath = __DIR__ . "/controller/" . $className . ".php"; if (is_file($classPath)) { require "{$classPath}"; return; } }); } public function onRequest($request, $response) { $response->header("Server", "SwooleServer"); $response->header("Content-Type", "text/html; charset=utf-8"); $server = $request->server; $path_info = $server['path_info']; $request_uri = $server['request_uri']; if ($path_info == '/favicon.ico' || $request_uri == '/favicon.ico') { return $response->end(); } $controller = 'Index'; $method = 'home'; if ($path_info != '/') { $path_info = explode('/',$path_info); if (!is_array($path_info)) { $response->status(404); $response->end('URL不存在'); } if ($path_info[1] == 'favicon.ico') { return; } $count_path_info = count($path_info); if ($count_path_info > 4) { $response->status(404); $response->end('URL不存在'); } $controller = (isset($path_info[1]) && !empty($path_info[1])) ? $path_info[1] : $controller; $method = (isset($path_info[2]) && !empty($path_info[2])) ? $path_info[2] : $method; } $result = "class 不存在"; if (class_exists($controller)) { $class = new $controller(); $result = "method 不存在"; if (method_exists($controller, $method)) { $result = $class->$method($request); } } $response->end($result); } } $server = new Server(); Index.php <?php class Index { public function home($request) { $get = isset($request->get) ? $request->get : []; //@TODO 業務代碼 $result = "<h1>你好,Swoole。</h1>"; $result.= "GET參數:".json_encode($get); return $result; } } Login.php <?php class Login { public function index($request) { $post = isset($request->post) ? $request->post : []; //@TODO 業務代碼 return "<h1>登錄成功。</h1>"; } }
小結
一、Swoole 可以替代 Nginx 嗎?
暫時不能,隨著 Swoole 越來越強大,以後說不准。
官方建議 Swoole 與 Nginx 結合使用。
Http\Server 對 Http 協議的支持並不完整,建議僅作為應用伺服器。並且在前端增加Nginx作為代理。
根據自己的 Nginx 配置文件,可以自行調整。
比如:可以新增一個配置文件
enable-swoole-php.conf location ~ [^/]\.php(/|$) { proxy_http_version 1.1; proxy_set_header Connection "keep-alive"; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://127.0.0.1:9501; }
我們都習慣於將虛擬功能變數名稱的配置文件放在 vhost 文件夾中。
比如,虛擬功能變數名稱的配置文件為:local.swoole.com.conf,可以選擇載入 enable-php.conf ,也可以選擇載入 enable-swoole-php.conf。
配置文件供參考:
server { listen 80; #listen [::]:80; server_name local.swoole.com ; index index.html index.htm index.php default.html default.htm default.php; root /home/wwwroot/project/swoole; #include rewrite/none.conf; #error_page 404 /404.html; #include enable-php.conf; include enable-swoole-php.conf; location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /.well-known { allow all; } location ~ /\. { deny all; } access_log /home/wwwlogs/local.swoole.com.log; }
當前,我們直接編輯 server 段的代碼也是可以的。
二、修改了 controller 文件夾中的業務代碼,每次都是重啟服務才生效嗎?
不是,每次重啟服務可能會影響到正常用戶使用的,正常處理的請求會被強制關閉。
在本地運行 路由控制 的代碼時,試試這個命令:
ps aux | grep swoole_process_server_master | awk '{print $2}' | xargs kill -USR1
給 master 進程發送一個 USR1 的信號,當 Swoole Server 接到這個信號後,就會讓所有 worker 在處理完當前的請求後,進行重啟。
如果查看所有的進程,試試這個命令:
ps -ef | grep 'swoole_process_server' | grep -v 'grep'
擴展
可以試著上傳文件,做一個小的FTP伺服器。
可以學習 Swoole 開源框架:EasySwoole、Swoft、One。
可以將 Swoole 整合到目前正在使用的PHP框架中。