Архитектура бэкенда CRC на Azure
Браузер → Azure Functions (HTTP trigger) → Cosmos DB (Serverless)
↓
Application Insights (мониторинг)
Cosmos DB Serverless
# Cosmos DB аккаунт (serverless)
az cosmosdb create \
--name crc-cosmos-db \
--resource-group crc-resources \
--capabilities EnableServerless \
--default-consistency-level Session
# База данных
az cosmosdb sql database create \
--account-name crc-cosmos-db \
--resource-group crc-resources \
--name crc-database
# Контейнер
az cosmosdb sql container create \
--account-name crc-cosmos-db \
--resource-group crc-resources \
--database-name crc-database \
--name counters \
--partition-key-path "/id"
# Начальные данные (через Azure Portal или SDK)
Azure Functions
Проект
# Инициализация проекта
func init crc-backend --python
cd crc-backend
func new --name count --template "HTTP trigger" --authlevel anonymous
Код функции (v2 programming model)
# function_app.py
import azure.functions as func
import json
import os
import logging
from azure.cosmos import CosmosClient, exceptions
app = func.FunctionApp()
# Initialize Cosmos client (outside function for reuse)
cosmos_client = CosmosClient.from_connection_string(
os.environ['COSMOS_CONNECTION_STRING']
)
database = cosmos_client.get_database_client('crc-database')
container = database.get_container_client('counters')
@app.route(route="count", methods=["GET"], auth_level=func.AuthLevel.ANONYMOUS)
def visitor_counter(req: func.HttpRequest) -> func.HttpResponse:
"""HTTP trigger for visitor counter."""
logging.info('Visitor counter triggered')
try:
# Read or create counter
try:
item = container.read_item(
item='visitor-count',
partition_key='visitor-count'
)
item['count'] += 1
except exceptions.CosmosResourceNotFoundError:
item = {'id': 'visitor-count', 'count': 1}
# Upsert (create or update)
container.upsert_item(item)
logging.info(f"Count updated to {item['count']}")
return func.HttpResponse(
json.dumps({'count': item['count']}),
mimetype='application/json',
headers={
'Access-Control-Allow-Origin': 'https://resume.ivanpetrov.com',
'Access-Control-Allow-Methods': 'GET'
}
)
except Exception as e:
logging.error(f'Error: {e}')
return func.HttpResponse(
json.dumps({'error': 'Service unavailable'}),
status_code=503,
mimetype='application/json'
)
host.json
{
"version": "2.0",
"extensions": {
"http": {
"routePrefix": "api"
}
},
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
}
}
requirements.txt
azure-functions
azure-cosmos>=4.5.0
Деплой
# Создаём Storage Account для Functions
az storage account create \
--name crcfuncstorage \
--resource-group crc-resources \
--location westeurope \
--sku Standard_LRS
# Создаём 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 \
--functions-version 4
# Устанавливаем connection string
COSMOS_CONN=$(az cosmosdb keys list \
--name crc-cosmos-db \
--resource-group crc-resources \
--type connection-strings \
--query 'connectionStrings[0].connectionString' --output tsv)
az functionapp config appsettings set \
--name crc-visitor-counter \
--resource-group crc-resources \
--settings "COSMOS_CONNECTION_STRING=$COSMOS_CONN"
# Деплой
func azure functionapp publish crc-visitor-counter
CORS
# Настройка CORS на Function App
az functionapp cors add \
--name crc-visitor-counter \
--resource-group crc-resources \
--allowed-origins "https://resume.ivanpetrov.com"
Тестирование
# Тест
curl https://crc-visitor-counter.azurewebsites.net/api/count
# {"count": 1}
# С CORS
curl -H "Origin: https://resume.ivanpetrov.com" \
https://crc-visitor-counter.azurewebsites.net/api/count
Какой auth_level рекомендуется для публичного API CRC?
A. ADMIN B. FUNCTION C. ANONYMOUS D. USER
Проверить
Что делает container.upsert_item() в Cosmos DB?
A. Только создаёт новый документ B. Создаёт документ если не существует, обновляет если существует C. Удаляет и создаёт заново D. Проверяет существование документа
Проверить
Что такое Consumption Plan в Azure Functions?
A. План потребления ресурсов B. Serverless модель: оплата за выполнение, автомасштабирование от 0, до 200 экземпляров C. Фиксированный план с ежемесячной оплатой D. План с reserved capacity
Проверить
Зачем Cosmos DB connection string хранится в App Settings, а не в коде?
A. Для удобства B. Connection string -- секрет, хранение в коде -- уязвимость (утечка через Git) C. Azure Functions не поддерживает hardcoded строки D. Для ускорения подключения
Проверить
Почему для CRC рекомендуется Cosmos DB Serverless, а не Provisioned?
A. Serverless быстрее B. Serverless: оплата только за запросы, нет минимальной платы -- идеально для низкой нагрузки CRC C. Provisioned не поддерживает Python D. Serverless имеет больше функций
Проверить