2021年3月3日 星期三

Laravel-S (Swoole 加速) 的初步探索整理

在測試了最熱門的 swooletw/laravel-swoole 不成功之後,再測熱門程度差了好幾個等級,甚至 Google "laravel swoole" 的關鍵字,在搜尋結果都不會出現的 hhxsv5/laravel-s,成功了,那就繼續探所下去吧。

首先,新手真的不曉得該如 rewrite rule,轉過來的 request,有啟動 php 程式,但一直出 match route 錯誤,真是讓人感到挫折灰心。後來根據錯誤訊息,追縱 Laravel 的原始碼,直接找到 Illuminate\Routing\Router.php,在出錯的那個 function,加上下列程式片段,這樣它就會在執行的命令視窗顯示轉過來的網址,再依此結果修正 rewrite rule。

findRoute($request)
{
    echo "findRoute\n";
    var_dump($request->getRequestUri()); exit;
    ....
} 

發現在沒有指定檔名,要開啟預設檔案時,會轉過來 index.html,解決方式是在 .htaccess 加入。
DirectoryIndex index.php

然後在 route.php 將 Route::get('/', ... 改成如下
Route::get('/index.php', function () { ... });
在 Laravel 中使用的 dump() 是 Symfony\Component\VarDumper::dump() 建立的 helper function,會呼叫 CliDumper(),其會將資料輸出到執行 laravels start 的命令視窗。

解決辦法,參考原程式,自己另建一個 dump()

static 變數的測試,噢,會互相影響,所以要改很多 ...,只能再看看吧!!

另一困擾,假如網頁不是放在伺服器的 DocumentRoot 目錄下,asset() 和 url() 不會加上網頁的目錄,如 http://ll.cc/blog/list ...,其中 blog 不會出現。這要改的也是不少。

解決辦法是修改檔案 app/Providers/AppServiceProvider.php 中的 boot method。
public function boot()
{
    \URL::forceRootUrl("http://localhost:8180/blog"); 
}

亦可將其定義在 .env 中,例如 APP_URL。只要加上兩行就能解決問題,算是不錯了。

經過反覆測試,最後修改 boot() 的內容如下,程式的其餘部份不用改太多就可順利執行。
/*
 * 此為 laravels.received_request, After LaravelS parsed Swoole\Http\Request 
 * to Illuminate\Http\Request, before Laravel's Kernel handles this request.
 */
public function boot()
{
    // 只會在 loading 時被 call 一次
    echo "===================\n";

    \Event::listen('laravels.received_request', 
        function (\Illuminate\Http\Request $req, $app) 
        {
            // 這裡才是真的透過 browser瀏覽
            // 才有某些關於 client 的 SERVER 資料
            // 去除附加的預設執行檔 index.php
            $req_uri = $req->server->get("REQUEST_URI");
            $def_php = '/index.php';

            if (substr($req_uri, 0, strlen($def_php)) == $def_php) {
                $req_uri = substr($req_uri, strlen($def_php));
                if ($req_uri == '') {
                    $req_uri = '/';
                }

                $req->server->set("REQUEST_URI", $req_uri);
            }

            // 看起來,root url 並不是依據 "HTTP_HOST" 產生的
            // 改變 "HTTP_HOST",並不會改變 url() 和 asset() 的結果
            // 但是又找不到其他變數含有 port 資料
            // $req_host = $req->server->get("HTTP_HOST");
            // echo $req_host."<br>\n";
            // $req->server->set("HTTP_HOST", $req_host.'abc');
            // $req->server->set("HTTP_HOST", env('URL_PATH'));
            var_dump($req->request->all());
            echo base_path()."<br>\n";
            // initialize static varibles
            Util_sw::clean();
            // $req->query->set('get_key', 'hhxsv5');// Change query of request
            // $req->request->set('post_key', 'hhxsv5'); // Change post of request
            // echo asset(env('URL_PATH'))."<br>\n";
            \URL::forceRootUrl('http://'.$req->server->get('HTTP_HOST').'/'.env('URL_PATH'));
        }
    );
    
    // echo request()->getPathInfo();
    // echo \URL::to('/')."<br>\n";
    // var_dump(getallheaders());
    // \URL::forceRootUrl(env("APP_URL")); 
}

在上面的程式片段中,加了一堆測試輸出訊息的程式,就是在摸索階段為了瞭解其特性而加的。其餘的再繼續整理中。

依照 Laravel-S 專案上的說明,將 Laravel 的 .htaccess 的內容修改如下,就是在檔案不存在時,轉到 laravel-s 伺服程式處理。而 Apache 的 httpd,在瀏覽目錄時,設定的預設程式是 index.html,在這裡把它改成 index.php。

# Alternate default index page
DirectoryIndex index.php

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$  balancer://laravels/$1 [P,L]
</IfModule>

針對上面的 rewrite rule,要修改 reverse proxy 的設定。
<IfModule deflate_module>
    SetOutputFilter DEFLATE
    DeflateCompressionLevel 2
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml
</IfModule>


RemoteIPHeader X-Forwarded-For

ProxyRequests Off
ProxyPreserveHost On

<Proxy balancer://laravels>  
    BalancerMember http://127.0.0.1:5200 loadfactor=7
    #BalancerMember http://192.168.1.2:5200 loadfactor=3
    #BalancerMember http://192.168.1.3:5200 loadfactor=1 status=+H
    ProxySet lbmethod=byrequests
</Proxy>

因為一個伺服器不只一個網頁程式,所以並未依照 Laravel-S 的說明,將網頁指向根目錄 (/)。為了解決此問題,測試了好久才搞定。


另外,不想修改網站設定,依自己的習慣調網站的目錄架構,將 public 目錄下的東西移到網頁的根目錄,程式則移到 web-src 下面,storage 不太好移,仍然放在 web-src 下,所以還需進一步修改 bin/laravels.php、artisan,bootstrap/autoload.php。


後續發展,經過半個多月的摸索,終於將一個自己維護的網站套上 Laravel-S 了,後面再開一篇文章來整理修改和注意的重點。





1 則留言:

網誌存檔