面試以後才知道,swoole完美支持TP5?!

協程是什麼

協程能夠理解爲純用戶態的線程,其經過協做而不是搶佔來進行切換,相對於進程或者線程,協程全部的操做均可以在用戶態完成,建立和切換的消耗更低,Swoole 能夠爲每個請求建立對應的協程,根據 IO 的狀態來合理的調度協程。php

在 Swoole 4.x 中,協程(Coroutine)取代了異步回調,成爲 Swoole 官方推薦的編程方式。Swoole 協程解決了異步回調編程困難的問題,使用協程能夠以傳統同步編程的方法編寫代碼,底層自動切換爲異步 IO,既保證了編程的簡單性,又可藉助異步 IO,提高系統的併發能力。html

完美支持TP5,首先開啓swoole的http服務

開啓swoole的http服務並設置提供給url訪問頁面的文件的根目錄,nginx

代碼以下。這樣在瀏覽器只能訪問…static下面的文件,而沒法訪問其餘目錄下的文件。laravel

http.serversql

<?php
//開啓http server
$http = new swoole_http_server("0.0.0.0", 9905);
$http->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/usr/local/openresty/nginx/html/swoole/LiveRadio/public/static",
        'worker_num' => 5
    ]
);
$http->on('request', function($request, $response) {
    $response->end("sss". json_encode($request->get));
});

$http->start();

swoole有一個事件回調函數onWorkStart,此事件在Worker進程/Task進程啓動時發生。這裏建立的對象能夠在進程生命週期內使用。thinkphp

原型:shell

function onWorkerStart(swoole_server $server, int workerid);編程

(1)onWorkerStart/onStart是併發執行的,沒有前後順序;json

(2)能夠經過server->taskworker屬性來判斷當前是Worker進程仍是Task進程;數組

(3)設置了worker_num和task_worker_num超過1時,每一個進程都會觸發一次onWorkerStart事件,可經過判斷$worker_id區分不一樣的工做進程;

(4)由 worker 進程向 task 進程發送任務,task 進程處理徹底部任務以後經過onFinish回調函數通知worker 進程。

例如,咱們在後臺操做向十萬個用戶羣發通知郵件,操做完成後操做的狀態顯示爲發送中,這時咱們能夠繼續其餘操做。等郵件羣發完畢後,操做的狀態自動改成已發送。

在onWorkerStart中加載框架的核心文件後:

(1)不用每次請求都加載框架核心文件,提升性能;

(2)能夠在後續的回調事件中繼續使用框架的核心文件或者類庫。

項目目錄下的public文件夾下的index.php是入口文件,源碼以下:

<?php
// [ 應用入口文件 ]
// 定義應用目錄
define('APP_PATH', __DIR__ . '/../application/');
// 加載框架引導文件
require __DIR__ . '/../thinkphp/start.php';

這個文件加載了…thinkphp/start.php’,start.php加載了一個核心文件base.php,因此咱們須要把base.php文件加載到onWorkStart回調函數裏面,每一個worker進程都會觸發一次onWorkerStart事件,所以ThinkPHP框架內的入口文件等內容就能加載入咱們的項目。

修改http.server以下:

<?php
//開啓http server
$http = new swoole_http_server("0.0.0.0", 9906);
$http->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/usr/local/openresty/nginx/html/swoole/LiveRadio/public/static",
        'worker_num' => 5  //設置worker進程數
    ]
);

$http->on('WorkerStart', function (swoole_server $server, $worker_id){
    //定義應用目錄
    define('APP_PATH', __DIR__ . '/../application/');
    // 加載基礎文件
    //這裏不直接加載start.php的緣由是start.php中的代碼會直接執行,也就是application\index\controller\Index.php文件(框架的默認首頁)
    /*
     * Container::get('app', [defined('APP_PATH') ? APP_PATH : ''])
    ->run()
    ->send();
    */
    require __DIR__ . '/../thinkphp/base.php';
});

$http->on('request', function($request, $response){
    //適配
    /*
     *因爲swoole http提供的API和原生php代碼是有所不一樣的,好比原生php中獲取get參數爲直接從全局數組_GET中獲取,而swoole http中是經過$request->get()的方式獲取,所以要轉換成原生的
     * */

    $_SERVER = [];
    if(isset($request->server)){
        foreach($request->header as $k => $v){
            $_SERVER[strtoupper($k)] = $v;
        }
    }
    $_GET = [];
    if(isset($request->get)){
        foreach($request->get as $k => $v){
            $_GET[$k] = $v;
        }
    }
    $_POST = [];
    if(isset($request->post)){
        foreach($request->post as $k => $v){
            $_POST[$k] = $v;
        }
    }

    //..其他參數用到的繼續日後寫

    ob_start();
    // 執行應用並響應
    try {
        think\Container::get('app', [APP_PATH])
            ->run()
            ->send();
    }catch (\Exception $e){
        //todo
    }
    $res = ob_get_contents();
    ob_end_clean();
    $response->end($res);
});

$http->start();

此時,用瀏覽器訪問 http://ip:port/?s=index/index/index 能夠看到ThinkPHP的默認首頁,可是發現訪問不到http://ip:port/?s=index/index/hello?name=world頁面。

能夠打印出路由看看。在項目目錄\thinkphp\library\think\App.php文件中的routeCheck接口,打印path變量,能夠看到url改變後path變量並無改變。這是由於onWorkerStart進程加載框架的時候就複用了類成員變量。

/**
     * URL路由檢測(根據PATH_INFO)
     * @access public
     * @return Dispatch
     */
    public function routeCheck()
    {
        $path = $this->request->path();
        echo "path:".$path."<br/>";
//        var_dump($this->request);
        $depr = $this->config('app.pathinfo_depr');

        // 路由檢測
        $files = scandir($this->routePath);
        foreach ($files as $file) {
            if (strpos($file, '.php')) {
                $filename = $this->routePath . DIRECTORY_SEPARATOR . $file;
                // 導入路由配置
                $rules = include $filename;
                if (is_array($rules)) {
                    $this->route->import($rules);
                }
            }
        }

        // 是否強制路由模式
        $must = !is_null($this->routeMust) ? $this->routeMust : $this->config('app.url_route_must');

        // 路由檢測 返回一個Dispatch對象
        return $this->route->check($path, $depr, $must, $this->config('app.route_complete_match'));
    }

修改:

進入 項目目錄\thinkphp\library\think\Request.php中

(1)找到function path() { },註銷判斷,再也不復用類成員變量 $ this->path。

(2)找到function pathinfo() { },註銷判斷,再也不復用類成員變量$this->pathinfo。

(3)使其支持pathinfo路由,在function pathinfo() { }中添加代碼

if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != '/') {
    return ltrim($_SERVER['PATH_INFO'], '/');
}

在這裏插入圖片描述

此時用瀏覽器訪問:
在這裏插入圖片描述

在這裏插入圖片描述

點關注,不迷路

好了各位,以上就是這篇文章的所有內容了,能看到這裏的人呀,都是人才。以前說過,PHP方面的技術點不少,也是由於太多了,實在是寫不過來,寫過來了你們也不會看的太多,因此我這裏把它整理成了PDF和文檔,若是有須要的能夠

點擊進入暗號: PHP+「平臺」

在這裏插入圖片描述

在這裏插入圖片描述


更多學習內容能夠訪問【對標大廠】精品PHP架構師教程目錄大全,只要你能看完保證薪資上升一個臺階(持續更新)

以上內容但願幫助到你們,不少PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那裏入手去提高,對此我整理了一些資料,包括但不限於:分佈式架構、高可擴展、高性能、高併發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階乾貨須要的能夠免費分享給你們,須要的能夠加入個人 PHP技術交流羣

相關文章
相關標籤/搜索