Files
sa-lessons/modules/module2/sections/05-serverless-architecture.md
Alexander Abakumov 15e744da49 Initial commit: Complete Software Architecture course with 11 modules
- Added comprehensive course structure with 11 modules
- Included theoretical content, practical examples, and tasks
- Multi-language code examples (Java, Rust, Node.js, Python)
- Detailed analysis of architectural approaches and trade-offs
- Complete caching strategies documentation
- Architecture examples from real-world systems (Twitter, Netflix, Uber)
- Structured navigation and learning path
- Ready for educational use
2025-09-09 22:08:07 +03:00

7.6 KiB
Raw Blame History

Serverless архитектура и FaaS

Навигация


Что такое Serverless

Serverless — это модель облачных вычислений, где разработчики не управляют серверами, а платформа автоматически выделяет ресурсы по требованию.

Ключевые характеристики Serverless

1. Event-Driven Execution

  • Функции запускаются по событиям
  • Автоматическое масштабирование
  • Оплата только за время выполнения

2. Stateless Functions

  • Функции не хранят состояние
  • Внешнее хранение данных
  • Горизонтальное масштабирование

FaaS (Функция как сервис)

FaaS — это подмодель Serverless, где код выполняется в виде отдельных функций.

AWS Lambda

# AWS Lambda Function
import json
import boto3

def lambda_handler(event, context):
    """
    Lambda function для обработки заказов
    """
    # Парсинг события
    order_data = json.loads(event['body'])
    
    # Валидация данных
    if not validate_order(order_data):
        return {
            'statusCode': 400,
            'body': json.dumps({'error': 'Invalid order data'})
        }
    
    # Обработка заказа
    order_id = process_order(order_data)
    
    # Отправка уведомления
    send_notification(order_id)
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'orderId': order_id,
            'status': 'processed'
        })
    }

def validate_order(order_data):
    """Валидация данных заказа"""
    required_fields = ['customerId', 'items', 'total']
    return all(field in order_data for field in required_fields)

def process_order(order_data):
    """Обработка заказа"""
    # Логика обработки заказа
    return f"ORD-{order_data.get('customerId')}-{int(time.time())}"

def send_notification(order_id):
    """Отправка уведомления"""
    sns = boto3.client('sns')
    sns.publish(
        TopicArn='arn:aws:sns:us-east-1:123456789012:order-notifications',
        Message=f'Order {order_id} has been processed',
        Subject='Order Processed'
    )

Azure Functions

// Azure Function
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

public static class OrderProcessor
{
    [FunctionName("ProcessOrder")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "orders")] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("Processing order request");

        try
        {
            // Чтение данных запроса
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var orderData = JsonSerializer.Deserialize<OrderData>(requestBody);

            // Валидация
            if (!ValidateOrder(orderData))
            {
                return new BadRequestObjectResult("Invalid order data");
            }

            // Обработка заказа
            var orderId = await ProcessOrderAsync(orderData);

            // Отправка уведомления
            await SendNotificationAsync(orderId);

            return new OkObjectResult(new { orderId, status = "processed" });
        }
        catch (Exception ex)
        {
            log.LogError(ex, "Error processing order");
            return new StatusCodeResult(500);
        }
    }

    private static bool ValidateOrder(OrderData orderData)
    {
        return !string.IsNullOrEmpty(orderData.CustomerId) &&
               orderData.Items?.Count > 0 &&
               orderData.Total > 0;
    }

    private static async Task<string> ProcessOrderAsync(OrderData orderData)
    {
        // Логика обработки заказа
        await Task.Delay(100); // Имитация обработки
        return $"ORD-{orderData.CustomerId}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
    }

    private static async Task SendNotificationAsync(string orderId)
    {
        // Отправка уведомления
        await Task.Delay(50); // Имитация отправки
    }
}

public class OrderData
{
    public string CustomerId { get; set; }
    public List<OrderItem> Items { get; set; }
    public decimal Total { get; set; }
}

Google Cloud Functions

// Google Cloud Function
const functions = require('@google-cloud/functions-framework');
const { PubSub } = require('@google-cloud/pubsub');

const pubsub = new PubSub();

functions.http('processOrder', async (req, res) => {
    // Установка CORS
    res.set('Access-Control-Allow-Origin', '*');
    res.set('Access-Control-Allow-Methods', 'POST');
    res.set('Access-Control-Allow-Headers', 'Content-Type');

    if (req.method === 'OPTIONS') {
        res.status(204).send('');
        return;
    }

    if (req.method !== 'POST') {
        res.status(405).send('Method Not Allowed');
        return;
    }

    try {
        const orderData = req.body;

        // Валидация данных
        if (!validateOrder(orderData)) {
            res.status(400).json({ error: 'Invalid order data' });
            return;
        }

        // Обработка заказа
        const orderId = await processOrder(orderData);

        // Отправка уведомления
        await sendNotification(orderId);

        res.status(200).json({
            orderId: orderId,
            status: 'processed'
        });
    } catch (error) {
        console.error('Error processing order:', error);
        res.status(500).json({ error: 'Internal server error' });
    }
});

function validateOrder(orderData) {
    const requiredFields = ['customerId', 'items', 'total'];
    return requiredFields.every(field => orderData.hasOwnProperty(field));
}

async function processOrder(orderData) {
    // Логика обработки заказа
    await new Promise(resolve => setTimeout(resolve, 100));
    return `ORD-${orderData.customerId}-${Date.now()}`;
}

async function sendNotification(orderId) {
    const topic = pubsub.topic('order-notifications');
    const message = {
        data: Buffer.from(JSON.stringify({
            orderId: orderId,
            message: `Order ${orderId} has been processed`
        }))
    };

    await topic.publish(message);
}

Преимущества Serverless

Технические:

  • Автоматическое масштабирование
  • Оплата только за использование
  • Отсутствие управления серверами
  • Быстрое развертывание

Экономические:

  • Снижение операционных расходов
  • Предсказуемые затраты
  • Отсутствие простоев серверов

Недостатки Serverless

Ограничения:

  • Cold Start задержки
  • Ограничения времени выполнения
  • Ограничения памяти
  • Vendor Lock-in

Сложности:

  • Сложность отладки
  • Ограниченный контроль
  • Проблемы с состоянием