聊聊 Vapor
近期对 Vapor 的无服务实现方式感兴趣,花了些时间研究了下其实践的机制。
什么是 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 集成)来链接我们的应用。所以它就可以画一张这样的图。
容器
在 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 的情况下,是否会因此导致账单很好看?这个不得不令人深思。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: