API Management (APIM) -- единая точка входа (API Gateway) для всех ваших API. Обеспечивает безопасность, мониторинг, throttling и документацию.
Архитектура APIM
Клиент -> APIM Gateway -> Backend API (App Service, Functions, AKS)
|
+-- Policies (inbound -> backend -> outbound -> on-error)
+-- Products (группировка API)
+-- Developer Portal (документация)
Компоненты:
- API Gateway -- принимает запросы, применяет политики, пересылает на backend
- Azure Portal -- настройка API, политик, продуктов
- Developer Portal -- автоматическая документация для разработчиков (OpenAPI/Swagger)
Политики (Policies)
Политики -- XML-инструкции, которые выполняются на каждом этапе обработки запроса.
Этапы обработки
<policies>
<inbound>
<!-- До отправки на backend -->
</inbound>
<backend>
<!-- При вызове backend -->
</backend>
<outbound>
<!-- После получения ответа от backend -->
</outbound>
<on-error>
<!-- При ошибке -->
</on-error>
</policies>
Rate Limiting
Ограничение количества запросов для защиты от перегрузки:
<policies>
<inbound>
<!-- 100 запросов в минуту на ключ подписки -->
<rate-limit calls="100" renewal-period="60" />
<!-- Или по IP-адресу -->
<rate-limit-by-key
calls="50"
renewal-period="60"
counter-key="@(context.Request.IpAddress)" />
<!-- Квота: 10000 запросов в неделю -->
<quota calls="10000" renewal-period="604800" />
</inbound>
</policies>
JWT-валидация
<policies>
<inbound>
<validate-jwt header-name="Authorization"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized">
<openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
<required-claims>
<claim name="aud" match="all">
<value>{client-id}</value>
</claim>
<claim name="roles" match="any">
<value>Orders.Read</value>
<value>Orders.Admin</value>
</claim>
</required-claims>
</validate-jwt>
</inbound>
</policies>
Кеширование ответов
<policies>
<inbound>
<!-- Проверить кеш -->
<cache-lookup vary-by-developer="false"
vary-by-developer-groups="false"
downstream-caching-type="none" />
</inbound>
<outbound>
<!-- Сохранить в кеш на 5 минут -->
<cache-store duration="300" />
</outbound>
</policies>
Трансформация запросов
<policies>
<inbound>
<!-- Добавление заголовка -->
<set-header name="X-Request-Source" exists-action="override">
<value>APIM</value>
</set-header>
<!-- Изменение URL -->
<rewrite-uri template="/api/v2/orders" />
<!-- Установка backend -->
<set-backend-service base-url="https://app-orderapp.azurewebsites.net" />
</inbound>
<outbound>
<!-- Удаление чувствительных заголовков -->
<set-header name="X-Powered-By" exists-action="delete" />
<set-header name="Server" exists-action="delete" />
</outbound>
</policies>
CORS
<policies>
<inbound>
<cors allow-credentials="true">
<allowed-origins>
<origin>https://myapp.com</origin>
</allowed-origins>
<allowed-methods>
<method>GET</method>
<method>POST</method>
</allowed-methods>
<allowed-headers>
<header>Authorization</header>
<header>Content-Type</header>
</allowed-headers>
</cors>
</inbound>
</policies>
Версионирование API
APIM поддерживает несколько стратегий:
- URL path:
/api/v1/orders,/api/v2/orders - Query string:
/api/orders?api-version=2.0 - Header:
Api-Version: 2.0
Products
Products группируют API и определяют условия доступа:
- Open -- доступен без подписки
- Starter -- бесплатный, с лимитами (100 запросов/мин)
- Premium -- платный, расширенные лимиты
Уровни APIM
| Уровень | Описание | Gateway SLA |
|---|---|---|
| Consumption | Serverless, оплата за вызов | 99.95% |
| Developer | Для разработки, без SLA | Нет SLA |
| Basic | Базовый production | 99.95% |
| Standard | VNet, multi-region | 99.95% |
| Premium | VNet, multi-region, WAF | 99.99% |
Event Grid
Помимо Service Bus, Azure предоставляет Event Grid для event-driven архитектуры:
// Публикация кастомного события
var client = new EventGridPublisherClient(
new Uri("https://topic-orderapp.eventgrid.azure.net/api/events"),
new AzureKeyCredential(topicKey));
var events = new List<EventGridEvent>
{
new EventGridEvent(
subject: $"/orders/{orderId}",
eventType: "Order.Created",
dataVersion: "1.0",
data: new { OrderId = orderId, Total = total })
};
await client.SendEventsAsync(events);
Event Grid vs Service Bus:
- Event Grid -- легковесные события, реактивная архитектура, push-модель
- Service Bus -- надежные сообщения, очереди, DLQ, транзакции, pull-модель