聊聊 Vapor

lxping發表於2019-12-02

近期對 Vapor 的無服務實現方式感興趣,花了些時間研究了下其實踐的機制。

Laravel Vapor is a serverless deployment platform for Laravel, powered by AWS.
Vapor是由AWS Lambda支援的Laravel無伺服器部署平臺。

Lambda 是一個標準的 Faas (Function as a service) 實現,而作為一個應用,Laravel 是怎麼在 Lambda 這個 Serverless 中實現執行的呢?

Kernel

首先我們看下入口檔案 index.php

$response = $kernel->handle(
  $request = Illuminate\Http\Request::capture()
);

$response->send();

當我們傳送一個請求是,Kernel::handle 方法將處理該請求並將響應傳送回瀏覽器。

我們通常的做法是,在伺服器中搭建一個 nginx 作為請求代理,使用 php-fpm 容器處理打到 index.php 的請求。

而 Vapor,則替我們實現了類似於 php-fpm 容器的功能,當然,還有比較多的封裝。

當應用在 Lambda 上執行時,就無法再將 public/index.php 作為單入口,因為 Lambda 並沒有 Apache, Nginx and
php-fpm。這時候就需要有一個 HTTP 層 (API 閘道器 + AWS lambda 整合)來連結我們的應用。所以它就可以畫一張這樣的圖。
聊聊 Vapor

容器

在 laravel 中,並無法直接識別 Lambda 的響應事件,所以這裡需要一個類似於 PHP-FPM 的容器,來接收所有的請求,並將其轉化為可以讓 laravel 識別的資料格式。

Laravel 將 HTTP 請求和響應與抽象在一起,同時又實現通過的 PSR-7,那麼我們要做的就是把 Lamada 的響應事件,轉化為 PSR-7 格式規範的物件,並傳給 Laravel。

aws 給閘道器到 Lambda 之間,設定了介面,AWS Lambda Runtime Interface
,那麼這個容器,我們需要實現的是 Next Invocation 以及 Invocation Response,從而實現輸入和輸出。

Lambda 執行 PHP

Lambda 無法直接執行 PHP, 這裡需要將 PHP 編譯好,並且打包上傳到 Lamabda,再通過 node spawn 執行,當然也可以選擇 Python 的 OS,隨各位的喜愛。

process.env['PATH']  =  process.env['PATH'] 
  +  ':'  +  process.env['LAMBDA_TASK_ROOT']  +  '/foo/bin'; 

const spawn = require('child_process').spawn;

exports.handle = function(event, context, callback) {

  let  script  =  spawn('php',  ['example.php',  JSON.stringify(event)]);
  script.stdout.on('data', (data) => {
    console.log(`stdout: ${data}`);
  });

  script.stderr.on('data', (data) => {
    console.log(`stderr: ${data}`);
  });

  script.on('close', (code) => {
    console.log(`child process exited with code ${code}`);
  });
}
## example.php
<?php
(function (array $event) {
    return [
        'hello' => $event['name'] ?? 'world',
    ];
});

利弊

Lamabda 屬於一個標準的無服務架構,所以對於我們來說,真的不需要關心運維,確實可以幫我們解決掉了很大一部分運維壓力。

但是不得不擔心的是,作為主要靠流量賺錢的雲平臺,在大流量,或者被惡意爬蟲甚至 DDOS 的情況下,是否會因此導致賬單很好看?這個不得不令人深思。

相關文章