- 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
258 lines
7.6 KiB
Markdown
258 lines
7.6 KiB
Markdown
# Serverless архитектура и FaaS
|
|
|
|
## Навигация
|
|
- [🏠 Главная страница курса](../../../README.md)
|
|
- [📚 Модуль 2](../README.md)
|
|
|
|
---
|
|
|
|
## Что такое Serverless
|
|
|
|
**Serverless** — это модель облачных вычислений, где разработчики не управляют серверами, а платформа автоматически выделяет ресурсы по требованию.
|
|
|
|
## Ключевые характеристики Serverless
|
|
|
|
### 1. Event-Driven Execution
|
|
- Функции запускаются по событиям
|
|
- Автоматическое масштабирование
|
|
- Оплата только за время выполнения
|
|
|
|
### 2. Stateless Functions
|
|
- Функции не хранят состояние
|
|
- Внешнее хранение данных
|
|
- Горизонтальное масштабирование
|
|
|
|
## FaaS (Функция как сервис)
|
|
|
|
**FaaS** — это подмодель Serverless, где код выполняется в виде отдельных функций.
|
|
|
|
### AWS Lambda
|
|
|
|
```python
|
|
# 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
|
|
|
|
```csharp
|
|
// 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
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
### Сложности:
|
|
- Сложность отладки
|
|
- Ограниченный контроль
|
|
- Проблемы с состоянием
|