Что такое serverless
Serverless -- это модель выполнения кода, где облачный провайдер полностью управляет серверной инфраструктурой. Вы пишете функцию, загружаете её, и провайдер сам решает, на каком сервере её запустить, как масштабировать и когда выключить.
Ключевые характеристики
- Нет управления серверами -- нет патчей, обновлений, мониторинга инфраструктуры
- Автоматическое масштабирование -- от 0 до тысяч экземпляров
- Оплата за использование -- платите только за время выполнения кода
- Event-driven -- функции запускаются в ответ на события (HTTP-запрос, сообщение в очереди, изменение в БД)
AWS Lambda
Создание функции для CRC
# lambda_function.py
import json
import boto3
from decimal import Decimal
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('visitor-counter')
def lambda_handler(event, context):
"""AWS Lambda handler for visitor counter."""
# Atomic increment
response = table.update_item(
Key={'id': 'visitors'},
UpdateExpression='ADD #count :inc',
ExpressionAttributeNames={'#count': 'count'},
ExpressionAttributeValues={':inc': Decimal('1')},
ReturnValues='UPDATED_NEW'
)
count = int(response['Attributes']['count'])
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({'count': count})
}
Деплой Lambda
# Упаковка кода
zip function.zip lambda_function.py
# Создание функции
aws lambda create-function \
--function-name visitor-counter \
--runtime python3.12 \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip \
--role arn:aws:iam::123456789012:role/lambda-crc-role \
--timeout 10 \
--memory-size 128
# Обновление кода
aws lambda update-function-code \
--function-name visitor-counter \
--zip-file fileb://function.zip
Конфигурация Lambda
| Параметр | Значение для CRC | Описание |
|---|---|---|
| Runtime | python3.12 | Версия Python |
| Memory | 128 MB | Минимум для CRC |
| Timeout | 10 секунд | Максимальное время выполнения |
| Architecture | arm64 | Дешевле на 20% |
| Reserved concurrency | 10 | Защита от DDoS |
Azure Functions
Создание функции
# function_app.py (Azure Functions v2 programming model)
import azure.functions as func
import json
import os
from azure.cosmos import CosmosClient
app = func.FunctionApp()
@app.route(route="count", methods=["GET"])
def visitor_counter(req: func.HttpRequest) -> func.HttpResponse:
"""Azure Function HTTP trigger for visitor counter."""
connection = os.environ['COSMOS_CONNECTION']
client = CosmosClient.from_connection_string(connection)
database = client.get_database_client('crc-db')
container = database.get_container_client('counters')
try:
item = container.read_item('visitor-count', partition_key='visitor-count')
item['count'] += 1
container.upsert_item(item)
except Exception:
item = {'id': 'visitor-count', 'count': 1}
container.create_item(item)
return func.HttpResponse(
json.dumps({'count': item['count']}),
mimetype='application/json',
headers={'Access-Control-Allow-Origin': '*'}
)
Деплой Azure Functions
# Создание Function App
az functionapp create \
--resource-group crc-resources \
--name crc-visitor-counter \
--consumption-plan-location westeurope \
--runtime python \
--runtime-version 3.11 \
--os-type Linux \
--storage-account crcfuncstorage
# Деплой кода
func azure functionapp publish crc-visitor-counter
Google Cloud Functions
Создание функции
# main.py
import functions_framework
from google.cloud import firestore
import json
db = firestore.Client()
@functions_framework.http
def visitor_counter(request):
"""Cloud Function for visitor counter."""
if request.method == 'OPTIONS':
return ('', 204, {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Access-Control-Max-Age': '3600'
})
counter_ref = db.collection('counters').document('visitors')
@firestore.transactional
def increment(transaction):
doc = counter_ref.get(transaction=transaction)
new_count = (doc.get('count') + 1) if doc.exists else 1
transaction.set(counter_ref, {'count': new_count})
return new_count
count = increment(db.transaction())
return (
json.dumps({'count': count}),
200,
{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
)
Деплой Cloud Functions
# Деплой (2nd gen -- рекомендуется)
gcloud functions deploy visitor-counter \
--gen2 \
--runtime=python312 \
--trigger-http \
--allow-unauthenticated \
--entry-point=visitor_counter \
--source=. \
--region=us-central1 \
--memory=128Mi \
--max-instances=10
Cold Start
Что такое Cold Start
Cold Start -- задержка при первом вызове функции после периода простоя. Провайдеру нужно время на:
- Выделение контейнера
- Загрузку runtime
- Загрузку вашего кода
- Инициализацию зависимостей
Сравнение Cold Start
| Провайдер | Cold Start (Python) | Warm Start |
|---|---|---|
| AWS Lambda | 200-500 мс | 1-5 мс |
| Azure Functions | 500-2000 мс | 1-10 мс |
| GCP Cloud Functions | 300-800 мс | 1-5 мс |
Как уменьшить Cold Start
- Минимизируйте пакет -- только нужные зависимости
- Используйте arm64 (Lambda) -- быстрее и дешевле
- Инициализация вне handler -- подключение к БД в глобальной области
- Provisioned Concurrency (Lambda) -- держит функции "тёплыми" (платно)
- Минимальный memory -- 128 MB достаточно для CRC
# ПРАВИЛЬНО: инициализация вне handler (переиспользуется между вызовами)
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('visitor-counter')
def lambda_handler(event, context):
# table уже инициализирована
response = table.update_item(...)
return response
# НЕПРАВИЛЬНО: инициализация внутри handler (каждый вызов заново)
def lambda_handler(event, context):
dynamodb = boto3.resource('dynamodb') # Медленно!
table = dynamodb.Table('visitor-counter') # Каждый раз!
...
Триггеры
Serverless-функции запускаются событиями (triggers):
| Триггер | AWS Lambda | Azure Functions | Cloud Functions |
|---|---|---|---|
| HTTP | API Gateway / Function URL | Built-in HTTP | Built-in HTTP |
| Очередь | SQS | Queue Storage | Pub/Sub |
| Хранилище | S3 Events | Blob Trigger | GCS Events |
| БД | DynamoDB Streams | Cosmos DB Trigger | Firestore Trigger |
| Расписание | EventBridge | Timer Trigger | Cloud Scheduler |
Для CRC используется HTTP trigger -- функция вызывается при HTTP GET-запросе.
Ценообразование
AWS Lambda
Бесплатно: 1M запросов + 400,000 GB-секунд / месяц
Платно:
- $0.20 за 1M запросов
- $0.0000166667 за GB-секунду
CRC: ~10,000 запросов/мес * 200 мс * 128 MB
= 0.025 GB-секунд = $0.00 (Free Tier)
Azure Functions (Consumption Plan)
Бесплатно: 1M запросов + 400,000 GB-секунд / месяц
Платно:
- $0.20 за 1M запросов
- $0.000016 за GB-секунду
CRC: те же расчёты = $0.00 (Free Tier)
GCP Cloud Functions
Бесплатно: 2M вызовов + 400,000 GB-секунд + 200,000 GHz-секунд
Платно:
- $0.40 за 1M вызовов
- $0.0000025 за GB-секунду
CRC: те же расчёты = $0.00 (Free Tier)
Для CRC стоимость serverless-функций на всех трёх провайдерах -- $0.00 в пределах Free Tier.