Swoole HTTP 的應用

咱們都知道 HTTP 是一種協議,容許 WEB 服務器和瀏覽器經過互聯網進行發送和接受數據。

想對 HTTP 進行詳細的瞭解,能夠找下其餘文章,這篇文章很少作介紹。

咱們在網上能看到的界面,圖片,動畫,音頻,視頻 等,都有依賴這個協議的。

在作 WEB 系統的時候,都使用過 IIS、Apache、Nginx 吧,咱們利用 Swoole 也能夠 簡單的實現一個 WEB 服務器。

主要使用了 HTTP 的兩大對象:Request 請求對象、Response 響應對象。

Request,包括 GET、POST、COOKIE、Header等。

Response,包括 狀態、響應體、跳轉、發送文件等。

很少說,先分享兩個程序:

    1、實現一個基礎的 Demo:「你好,Swoole.」

    2、實現一個簡單的 路由控制

本地版本:

    PHP 7.2.6

    Swoole 4.3.1

代碼

1、Demo:「你好,Swoole.」

示例效果:



備註:IP 地址是個人虛擬機。

示例代碼:

 php

   <?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();

 



2、路由控制

示例效果:



目錄結構:

    ├─ swoole_http  -- 代碼根目錄    
    │  ├─ server.php    
    │  ├─ controller    
    │     ├── Index.php    
    │     ├── Login.php

示例代碼:

css

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>";    
        }    
    }

 


小結

1、Swoole 能夠替代 Nginx 嗎?

暫時不能,隨着 Swoole 愈來愈強大,之後說不許。

官方建議 Swoole 與 Nginx 結合使用。

    Http\Server 對 Http 協議的支持並不完整,建議僅做爲應用服務器。而且在前端增長Nginx做爲代理。

根據本身的 Nginx 配置文件,能夠自行調整。

好比:能夠新增一個配置文件html

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 段的代碼也是能夠的。

2、修改了 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框架中。

json

相關文章
相關標籤/搜索