Введение: Почему Serverless и PHP — это не оксюморон
Долгое время считалось, что PHP и serverless-архитектура несовместимы. PHP ассоциировался с вечными процессами Apache или Nginx, а serverless — с Node.js или Python. Однако с появлением инструментов вроде Bref и официальной поддержки пользовательских сред выполнения (Custom Runtimes) в AWS Lambda, PHP получил второе дыхание.
Serverless-функции позволяют запускать PHP-код без управления сервером. Вы платите только за фактическое время выполнения (с точностью до миллисекунды). Это идеальное решение для:
- Обработчиков вебхуков (Telegram, Stripe, Slack);
- Микросервисов с низкой нагрузкой;
- Периодических задач (cron) через CloudWatch Events;
- API-прокси и легких бэкендов.
В этой статье мы разберем, как поднять PHP на AWS Lambda с нуля: от создания IAM-ролей до деплоя рабочей функции.
1. Архитектура PHP в AWS Lambda
Как работает Custom Runtime
AWS Lambda изначально поддерживает только Java, Go, PowerShell, Node.js, C#, Python и Ruby. Чтобы запустить PHP, мы используем Custom Runtime — это специальный исполняемый файл (bootstrap), который общается с Lambda Runtime API.
Самый популярный способ — фреймворк Bref. Он поставляется с готовым слоем (Layer), содержащим PHP 8.x, Composer и набор стандартных расширений.
// Структура проекта для Bref
project/
├── index.php // Точка входа
├── composer.json
├── serverless.yml // Конфигурация деплоя
└── vendor/
Три способа деплоя
- Bref (рекомендуемый) — самый простой. Использует serverless.yml и готовые слои.
- Ручная сборка — вы компилируете PHP под Amazon Linux 2 и упаковываете в ZIP.
- Docker-образ — используете Lambda Container Image (поддерживается с 2020 года).
Мы рассмотрим первый вариант — он подходит для 90% задач.
2. Пошаговая настройка: от установки до первого запроса
Шаг 1. Подготовка окружения
Убедитесь, что у вас установлены:
- PHP 8.0+ (локально)
- Composer
- Node.js и npm (для Serverless Framework)
- Утилита
aws-cliс настроенными credentials
Устанавливаем Serverless Framework глобально:
npm install -g serverless
Шаг 2. Создаем проект
composer create-project bref/bref my-php-lambda
cd my-php-lambda
После инициализации вы увидите файл serverless.yml. Отредактируем его:
service: my-php-app
provider:
name: aws
region: eu-central-1 # Выберите ближайший регион
runtime: provided.al2 # Amazon Linux 2
plugins:
- ./vendor/bref/bref
functions:
hello:
handler: index.php
description: 'Простая PHP функция'
layers:
- ${bref:layer.php-80} # Слой с PHP 8.0
Шаг 3. Пишем саму функцию
Откройте index.php:
<?php
require __DIR__ . '/vendor/autoload.php';
/**
* Обработчик Lambda-функции
* @param array $event Входные данные от AWS (API Gateway, SQS и т.д.)
* @return array Ответ в формате JSON
*/
function handler(array $event): array
{
// Логируем в CloudWatch
error_log('Получен запрос: ' . json_encode($event));
$name = $event['queryStringParameters']['name'] ?? 'Гость';
return [
'statusCode' => 200,
'headers' => [
'Content-Type' => 'application/json',
],
'body' => json_encode([
'message' => "Привет, {$name}!",
'timestamp' => time(),
]),
];
}
Шаг 4. Деплой
serverless deploy
После завершения вы увидите URL вашей функции. Проверим её через curl:
curl "https://YOUR_API_GATEWAY_URL?name=Мир"
Ответ:
{"message":"Привет, Мир!","timestamp":1698765432}
3. Продвинутые техники и оптимизация
Работа с переменными окружения
Не храните секреты в коде. Используйте .env файлы и сервис AWS Secrets Manager:
// serverless.yml
provider:
environment:
DB_HOST: ${ssm:/myapp/db/host} # Из Parameter Store
APP_KEY: ${env:APP_KEY} # Из локального .env
Обработка разных триггеров
Одна функция может обрабатывать события от разных сервисов. Пример для SQS:
// index.php — обработчик очереди
function handler(array $event): void
{
foreach ($event['Records'] as $record) {
$body = json_decode($record['body'], true);
// Ваша логика обработки
echo "Обработано сообщение: " . $body['id'] . PHP_EOL;
}
}
Холодный старт и как с ним бороться
Первое выполнение функции всегда медленнее (загрузка PHP, инициализация классов). Решения:
- Provisioned Concurrency — держит N экземпляров "горячими";
- Оптимизация автозагрузчика — используйте
composer dump-autoload -o; - Минимизация зависимостей — не тяните лишние библиотеки.
// composer.json — оптимизация
{
"autoload": {
"classmap": ["src/"] // Быстрее, чем PSR-4
},
"scripts": {
"compile": [
"@php -r \"file_put_contents('vendor/autoload.php', str_replace('require __DIR__', 'require_once __DIR__', file_get_contents('vendor/autoload.php')));