Serverless функции на JavaScript: AWS Lambda – полное руководство

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

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

Начать курс

Введение в Serverless архитектуру и AWS Lambda

Современная веб-разработка стремительно движется в сторону бессерверных (serverless) вычислений. Эта парадигма позволяет разработчикам сосредоточиться на написании бизнес-логики, не заботясь об управлении инфраструктурой. AWS Lambda — один из самых популярных сервисов для реализации serverless функций, и он отлично сочетается с JavaScript (Node.js).

В этой статье мы подробно разберем, что такое AWS Lambda, как создать и запустить свою первую serverless функцию на JavaScript, рассмотрим лучшие практики и примеры реального кода. Материал будет полезен как новичкам, так и опытным разработчикам, желающим освоить serverless-разработку.

Что такое AWS Lambda и как она работает с Node.js

AWS Lambda — это вычислительный сервис, который запускает ваш код в ответ на события и автоматически управляет вычислительными ресурсами. Вы платите только за потребленное время выполнения (с округлением до 1 мс) и количество запросов.

Ключевые особенности AWS Lambda для JavaScript-разработчика

  • Поддержка Node.js: AWS Lambda официально поддерживает Node.js 14, 16, 18 и 20.
  • Автоматическое масштабирование: Lambda автоматически создает экземпляры функции для обработки каждого входящего запроса.
  • Триггеры: Функции можно вызывать по HTTP (через API Gateway), по расписанию (CloudWatch Events), при загрузке файла в S3 и многими другими способами.
  • Ограничения: Время выполнения до 15 минут, память от 128 МБ до 10 240 МБ, размер пакета до 50 МБ (сжатый) или 250 МБ (распакованный).

Для работы с Lambda на JavaScript не требуется никакой дополнительной настройки — просто напишите обработчик (handler) и загрузите код в AWS.

Создание первой serverless функции на JavaScript

Давайте напишем простую serverless функцию, которая принимает JSON с именем пользователя и возвращает приветствие. Это классический пример, с которого стоит начать знакомство с AWS Lambda.

Шаг 1: Базовая структура обработчика

Каждая Lambda-функция на Node.js состоит из экспортируемой функции-обработчика, которая принимает три параметра: event (событие), context (контекст выполнения) и callback (для асинхронного ответа).

// index.js
exports.handler = async (event, context) => {
    // Логика функции
    const name = event.name || 'Гость';
    return {
        statusCode: 200,
        body: JSON.stringify({
            message: `Привет, ${name}! Это твоя первая serverless функция.`
        })
    };
};

Шаг 2: Обработка разных типов событий

В реальных проектах события могут приходить из разных источников. Рассмотрим пример обработки запроса от API Gateway:

// handler.js
exports.handler = async (event) => {
    try {
        // Парсим тело запроса (если оно есть)
        const body = event.body ? JSON.parse(event.body) : {};
        const { userId, action } = body;

        // Пример бизнес-логики
        const result = {
            userId: userId || 'unknown',
            action: action || 'default',
            timestamp: new Date().toISOString(),
            message: 'Действие выполнено успешно'
        };

        return {
            statusCode: 200,
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*'
            },
            body: JSON.stringify(result)
        };
    } catch (error) {
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

Работа с внешними сервисами и окружением

Serverless функции редко работают в изоляции. Чаще всего им нужно взаимодействовать с базами данных, S3, DynamoDB или вызывать другие сервисы AWS.

Пример: функция для работы с DynamoDB

В этом примере мы сохраняем данные пользователя в таблицу DynamoDB:

// userHandler.js
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const TABLE_NAME = process.env.TABLE_NAME || 'Users';

exports.handler = async (event) => {
    try {
        const { userId, name, email } = JSON.parse(event.body);

        const params = {
            TableName: TABLE_NAME,
            Item: {
                userId: userId,
                name: name,
                email: email,
                createdAt: new Date().toISOString()
            }
        };

        await dynamoDb.put(params).promise();

        return {
            statusCode: 201,
            body: JSON.stringify({
                message: 'Пользователь создан',
                userId: userId
            })
        };
    } catch (error) {
        return {
            statusCode: 500,
            body: JSON.stringify({ error: 'Ошибка при сохранении пользователя' })
        };
    }
};

Использование переменных окружения

Для хранения конфиденциальных данных (ключей API, имен таблиц) используйте переменные окружения. Они задаются в настройках функции AWS Lambda и доступны через process.env.

// config.js
const config = {
    dbTableName: process.env.TABLE_NAME,
    apiKey: process.env.API_KEY,
    region: process.env.AWS_REGION || 'us-east-1'
};

// Использование в функции
exports.handler = async (event) => {
    console.log(`Работаем в регионе: ${config.region}`);
    // ... остальной код
};

Оптимизация и лучшие практики

Чтобы ваши serverless функции работали быстро и экономично, следуйте этим рекомендациям:

1. Холодный старт (Cold Start)

Первое выполнение функции после простоя может занимать больше времени (холодный старт). Для уменьшения этого эффекта:

  • Используйте минимальное количество зависимостей в node_modules.
  • Подключайте AWS SDK только для нужных сервисов (используйте @aws-sdk/client-dynamodb вместо полного SDK).
  • Увеличьте выделенную память — это часто ускоряет и холодный старт, и выполнение.

2. Повторное использование соединений

Инициализируйте подключения к базам данных и HTTP-клиентам вне обработчика, чтобы они переиспользовались между вызовами:

// Оптимизированная версия
const AWS = require('aws-sdk');
// Инициализация вне handler — будет переиспользована
const dynamoDb = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
    // Здесь используем уже готовое соединение
    const data = await dynamoDb.scan({ TableName: 'Orders                

Блоги

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