LaravelConf 2018《優雅與效能,Laravel 與 swoole 整合之路》筆記

xing393939發表於2020-06-20

線上視訊

  1. www.pilishen.com/casts/speed-up-la...

laravel為什麼慢

  1. 一次請求差不多要載入200多個php,當然也可以用opcache
  2. 每次請求結束,所有資源都被銷燬,不能重複利用。下面有一個laravel的請求生命週期圖:

和swoole整合的方案

方案1

把swoole當php-fpm一樣使用,每次處理請求都載入一下laravel核心,其實還是不能避免每次都載入200多個php,程式碼如下:

public function onRequest($swooleRequest, $swooleResponse) {
    $app = require_once __DIR__.'/bootstrap/app.php';
    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
    $illuminateRequest = Request::make($swooleRequest)->toIlluminate();
    $illuminateResponse = $kernel->handle($illuminateRequest);
    $response->end($illuminateResponse->getContent());
    $kernel->terminate($illuminateRequest, $illuminateResponse);
}

方案2

公用一個laravel容器,程式碼如下:

public function onRequest($swooleRequest, $swooleResponse) {
    $app = $this->getApplication();
    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
    $illuminateRequest = Request::make($swooleRequest)->toIlluminate();
    $illuminateResponse = $kernel->handle($illuminateRequest);
    $response->end($illuminateResponse->getContent());
    $kernel->terminate($illuminateRequest, $illuminateResponse);
}

這個方案對比方案1,可以不用重複載入php了,laravel的請求生命週期圖如下:

這個方案的問題是如果A使用者登入了,B使用者訪問swoole同一個worker的時候也是登入狀態,因為AuthManager是單例,同一個程式是資料共享的。實際上,單例、全域性變數、靜態屬性也都是資料共享的。這樣就造成資料安全問題了。

方案3

基於方案2,每次獲取容器例項後,清理掉單例物件,理論上可行,但是太繁瑣了

方案4

基於方案2,第一次laravel容器初始化並註冊服務提供者和例項後,就克隆一個乾淨的物件sandBox。每次請求都基於sandBox做後續的處理,sandBox每次都會reset一下。
這個方案的laravel的請求生命週期圖如下:

此方案的GitHub地址是:github.com/swooletw/laravel-swoole

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章