Swoole HTTP 的應用

来源:https://www.cnblogs.com/it-3327/archive/2019/11/07/11815835.html

我們都知道 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框架中。


您的分享是我們最大的動力!

更多相關文章
  • Python繪圖庫Turtle Turtle介紹 Turtle是Python內嵌的繪製線、圓以及其他形狀(包括文本)的圖形模塊。 一個Turtle實際上是一個對象,在導入Turtle模塊時,就創建了對象,然後,可以調用Turtle對象的各種方法完成不同的操作。 當創建一個Turtle對象時,它的位置 ...
  • 寫在前面的話 適用讀者:有一定經驗的,本文不適合初學者,因為可能不能理解我在說什麼 文章思路:不會一開始就像別的博客文章那樣,Bean 的生命周期,源碼解讀(給你貼一大堆的源碼)。個人覺得應該由問題驅動,為什麼為出現 BeanFactory ,為什麼會有生命周期。 正文 一開始我們使用 bean 都 ...
  • 1、Eureka服務端集群開發 1、先創建一個父工程 若是不是普通demo,還有別的配置時,需要註意若是服務開不起來可能就是父類依賴中可能會需要<dependencyManagement>這個標簽。 2、再創建兩個子工程 1、導入依賴 <dependency> <groupId>org.spring ...
  • 1 簡介 我們知道 只是一個介面,它有多種實現,Java中最常用的是 了。而本文想講述的是另一個實現: 。它是枚舉類型的 ,要求它的Key值都必須是枚舉型的。 2 創建你的EnumMap 既然是關於枚舉類型的Map,我們先創建一個枚舉,以便後續使用: 2.1 創建EnumMap的三種方法 JDK提供 ...
  • 1. lamda匿名函數 為瞭解決⼀些簡單的需求⽽設計的⼀句話函數 # 計算n的n次⽅ def func(n): return n**n print(func(10)) f = lambda n: n**n print(f(10)) lambda表⽰的是匿名函數,不需要⽤def來聲明,⼀句話就可以聲 ...
  • 調優基本概念 在調整JVM性能時,通常有三個組件需要考慮: 堆大小調整 垃圾收集器調整 JIT編譯器 大多數調優選項都與調整堆大小和選擇合適的垃圾收集器有關,JIT編譯器對性能也有很大影響,但很少需要對其進行調優,尤其是針對較新版本的JVM。 通常,在進行Java程式調優的時候,會重點關註兩個主要指 ...
  • 這篇文章主要分享 Timer 毫秒精度的定時器。本地版本:PHP 7.2.6、Swoole 4.3.1。Timer主要有三個方法:swoole_timer_tick 間隔的時鐘控制器swoole_timer_after 指定的時間後執行swoole_timer_clear 刪除定時器示例代碼:運行結 ...
  • 包裝 1.二次加工標準類型(包裝) class List(list): def append(self, a_objcet): if type(a_objcet) is str: super().append(a_objcet) else: print('請傳入字元轉類型') l1 = List(' ...
一周排行
  • 前幾天發佈了 "抄抄《CSS 故障藝術》的動畫" 這篇文章,在這篇文章里介紹瞭如何使用Win2D繪製文字然後配合BlendEffect製作故障藝術的動畫。本來打算就這樣收手不玩這個動畫了,但後來又發現性能不符合理想。明明只是做做Resize動畫和用BlendEffect混合,為什麼性能會這麼差呢? ...
  • 控制條控制項: progressBar 不能按照你程式的進程自動變化,需認為計算,調整變化量 private void progressBar1_Click(object sender, EventArgs e) { this.progressBar1.Maximum = 100;//設置進度條最大長 ...
  • 首先創建一個asp.net core web應用程式 第二步 目前官方預置了7種模板項目供我們選擇。從中我們可以看出,既有我們熟悉的MVC、WebAPI,又新添加了Razor Page,以及結合比較流行的Angular、React前端框架的模板項目。 空項目模板 Program.cs using S ...
  • 對閉包的理解 1.對於成員變數和局部變數:成員變數就是方法外部,類的內部定義的變數;局部變數就是方法或語句塊內部定義的變數。局部變數必須初始化。 形式參數是局部變數,局部變數的數據存在於棧記憶體中。棧記憶體中的局部變數隨著方法的消失而消失。成員變數存儲在堆中的對象裡面,由垃圾回收器負責回收。 成員變數它 ...
  • Xamarin.Forms讀取並展示Android和iOS通訊錄 TerminalMACS客戶端 本文同步更新地址: https://dotnet9.com/11520.html https://terminalmacs.com/861.html 閱讀導航: 一、功能說明 二、代碼實現 三、源碼獲取 ...
  • 做下對文件複製操作相關的筆記: /// <summary> /// 文件幫助類 /// </summary> public class FileHelper { /// <summary> /// 複製一個目錄下所有文件到一個新目錄下 /// </summary> /// <param name=" ...
  • 前言 有一個東西叫做鴨子類型,所謂鴨子類型就是,只要一個東西表現得像鴨子那麼就能推出這玩意就是鴨子。 C 裡面其實也暗藏了很多類似鴨子類型的東西,但是很多開發者並不知道,因此也就沒法好好利用這些東西,那麼今天我細數一下這些藏在編譯器中的細節。 不是只有 和 才能 在 C 中編寫非同步代碼的時候,我們經 ...
  • [toc] 1.應用背景 底端設備有大量網路報文(位元組數組):心跳報文,數據採集報文,告警報文上報。需要有對應的報文結構去解析這些位元組流數據。 2.結構體解析 由此,我第一點就想到了用結構體去解析。原因有以下兩點: 2.1.結構體存在棧中 類屬於引用類型,存在堆中;結構體屬於值類型,存在棧中,在一個 ...
  • 《深入淺出 C#》 (第3版) [作者] (美) Andrew Stellman (美) Jennifer Greene[譯者] (中) 徐陽 丁小峰 等譯[出版] 中國電力出版社[版次] 2016年08月 第1版[印次] 2018年04月 第4次 印刷[定價] 148.00元 【引子】 要學習編程 ...
  • 記錄使用對象初始值設定項初始化對象。 using System; using System.Collections.Generic; namespace ConsoleApp2 { class Program { static void Main(string[] args) { // 使用構造函數 ...
x