Serverless функции на PHP: AWS Lambda от А до Я — полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему 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/

Три способа деплоя

  1. Bref (рекомендуемый) — самый простой. Использует serverless.yml и готовые слои.
  2. Ручная сборка — вы компилируете PHP под Amazon Linux 2 и упаковываете в ZIP.
  3. 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')));                

Блоги

Рекомендаций по книгам