PHP 无服务器函数:AWS Lambda — 从理论到高级实践
无服务器架构早已不再是新鲜事物,而 PHP 凭借 Bref 和 Laravel Vapor 等工具,在无服务器计算领域稳稳占据了一席之地。本文将深入探讨在 AWS Lambda 上使用 PHP 的高级技术:如何攻克冷启动、在 VPC 内部进行配置,以及高效处理来自 S3 和 SQS 的事件。本文面向已掌握在 Lambda 上部署 PHP 应用程序基础知识的开发者。
1. 冷启动优化:从 2 秒到 200 毫秒
PHP 无服务器应用的头号敌人是冷启动。与 Node.js 或 Python 不同,PHP 需要加载解释器和框架。以下是最大限度减少延迟的方法。
1.1. 使用 Bref 和预编译层
Bref 是在 Lambda 上运行 PHP 的事实标准。它提供了包含 PHP 解释器的现成层(Layers)。为了加速,请使用 bref/extra-php-extensions 并仅连接必要的扩展。
serverless.yml 基本配置示例:
service: my-php-app
provider: name: aws runtime: provided.al2 region: eu-central-1
plugins: - ./vendor/bref/bref
functions: api: handler: public/index.php layers: - ${bref:layer.php-81} events: - httpApi: '*'1.2. 延迟加载与配置缓存
不要在每次请求时都加载整个框架(Laravel、Symfony)。使用 Laravel Octane 配合 Swoole 或 RoadRunner,但对于 Lambda,Bref Laravel Bridge 更为合适,它可以缓存配置和路由。
bootstrap.php 中的配置缓存代码:
// public/index.php (Lambda 入口点)require_once __DIR__ . '/../vendor/autoload.php';
$app = require_once __DIR__ . '/../bootstrap/app.php';
// 首次运行时缓存配置if (! file_exists(__DIR__ . '/../bootstrap/cache/config.php')) { $app->make('config')->get('app'); // 保存编译后的配置 file_put_contents( __DIR__ . '/../bootstrap/cache/config.php', '<?php return ' . var_export($app->make('config')->all(), true) . ';' );} else { $config = require __DIR__ . '/../bootstrap/cache/config.php'; $app->instance('config', $config);}
$kernel = $app->make(Illuminate\\Contracts\\Http\\Kernel::class);$response = $kernel->handle( $request = Illuminate\\Http\\Request::capture());$response->send();$kernel->terminate($request, $response);建议: 将 memorySize 设置为 1024 MB,timeout 设置为 30 秒,以平衡速度和成本。内存越大,CPU 速度越快。
2. VPC 集成:连接 RDS 和 ElastiCache
默认情况下,Lambda 函数在您的 VPC 之外运行。要访问数据库(RDS、Aurora)或缓存(ElastiCache),需要将函数部署在 VPC 内部。这会增加复杂性,并使冷启动时间延长 5-10 秒。
2.1. 在 serverless.yml 中配置 VPC
functions: processUser: handler: src/handlers/userHandler.php layers: - ${bref:layer.php-81} vpc: securityGroupIds: - sg-0123456789abcdef0 subnetIds: - subnet-abc123 - subnet-def456 events: - sqs: arn: arn:aws:sqs:eu-central-1:123456789012:user-queue2.2. 通过 PDO 管理连接
使用 RDS Proxy 连接池 或 ElastiCache,以便在单个 Lambda 容器内重复使用连接。
数据库操作类示例(带连接复用):