Ordre 20260912T193441Z-7358817909. Steg 1 var ikke transformen, men å rette
roadmapens R13-gate og få den ratifisert. Gaten `grep -rl "Cosmo"
skills/*/references -> 0` var usann på to uavhengige måter:
1. Ordren fanget den første: 451 av forekomstene er Azure Cosmos DB, ekte
produktinnhold. Diskriminatoren er ikke bokstaven «s» — `Cosmos <norsk
substantiv>` er genitiv av personaen (`### Cosmos tonalitet`), mens
`Cosmos DB`/`CosmosClient`/`cosmos_ru` er produkt.
2. Denne økten fant den andre: 132 persona-forekomster ligger i prosa,
tabeller, dialog-replikker og proveniens-linjer. Heading-nøytralisering
kan ikke nå dem, så «0 persona» er uoppnåelig også under den ratifiserte
formen. Operatøren ratifiserte alternativ A: gaten speiler formen, og de
132 bokføres til R13b/R14.
Tre korreksjoner av premisser som sto i ordren og STATE:
«ca 320 produkt» -> 451 (case-sensitivt nett manglet 327 lowercase
TOC-ankre + 99 identifikatorer; sann nevner 1 638)
«169 headinger» -> 401. 169 var `^## For Cosmo`-prefikset (168) og var
internt inkonsistent med sin egen topp-variant (204)
«417 matcher ingen
populasjon» -> 417 er cosmo-headinger utenfor kodefences; briefens
nevner var reell hele tiden
Fence-bevissthet er målt skadelig, ikke nødvendig: begge toggle-regler er
gale på dette korpuset (naiv toggle skjuler en ekte heading i
chain-of-thought-prompting.md, CommonMark-regelen ubalanserer
service-level-documentation-dr.md). Fence-agnostisk deteksjon finner 401
heading-linjer i nøyaktig de samme 40 variantene som fence-bevisst finner
400 i — ingen kodeblokk-linje er byte-identisk til en persona-heading. Derfor
nøkles transformen på 40 enumererte heading-tekster og ignorerer fences. En
ukjent variant kaster; en slug-kollisjon kaster. Ingenting auto-fikses.
TOC-en regenereres ikke, den rettes kirurgisk: alle 327 persona-lenker hadde
lenketekst lik én av de 40 heading-tekstene og anker lik slugify av den
(327/327, 0 avvik), så heading og TOC-entry skrives i samme operasjon og
ingen mellomtilstand etterlater en død lenke.
Ratifisert målform: `For Cosmo`, `For Cosmo Skyberg` og `For arkitekten
(Cosmo)` konvergerer på `For arkitekten`. To filer kolliderte og er adjudisert
ved å lese dem, ikke ved regel.
Verifisering (alle 7 kriterier fra ordren):
G1 persona på heading-linjer 401 -> 0
G2 døde fragmentlenker 1 -> 1 (pre-eksisterende, unntatt)
G3 produkt-forekomster 451 -> 451; `Cosmos DB|Azure Cosmos` 308 = 308
de 3 kun-produkt-filene byte-identiske
nettet validert begge veier injisert persona feller G1; genitiv feller G1;
produkt-heading og de 3 filene passerer
hele diffen 802 heading-linjer + 654 TOC-linjer, ANNET = 0
linjeantall 728 lagt til = 728 slettet
suite 1120/1120 (1097 + 23 nye)
validate-plugin 250 PASS / 0 FAIL
stikkprøve 10 filer, alle 5 skills, inkl. de 3 mest
produkt-tunge (26/20/19) — kun heading+TOC
Utenfor scope, urørt: de 4 SKILL.md, de 23 commands, CLAUDE.md, README.md,
NOTICE.md, docs/ (alt R14).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
649 lines
18 KiB
Markdown
649 lines
18 KiB
Markdown
# Load Balancing Across Azure OpenAI Instances
|
|
|
|
**Last updated:** 2026-02
|
|
**Status:** GA
|
|
**Category:** API Management & AI Gateway
|
|
**Type:** reference
|
|
|
|
---
|
|
|
|
## Innhold
|
|
|
|
- [Introduksjon](#introduksjon)
|
|
- [Backend Pool-konsepter](#backend-pool-konsepter)
|
|
- [Load Balancing-strategier](#load-balancing-strategier)
|
|
- [Individual Backend-konfigurasjon](#individual-backend-konfigurasjon)
|
|
- [Deployment Slot Selection](#deployment-slot-selection)
|
|
- [Regional Distribution](#regional-distribution)
|
|
- [Throttling og Retry-håndtering](#throttling-og-retry-håndtering)
|
|
- [Komplett Bicep-eksempel](#komplett-bicep-eksempel)
|
|
- [Overvåking og feilsøking](#overvåking-og-feilsøking)
|
|
- [For arkitekten](#for-arkitekten)
|
|
|
|
## Introduksjon
|
|
|
|
Lastbalansering på tvers av flere Azure OpenAI-instanser er en kritisk kapabilitet for enterprise AI-arkitekturer. Azure OpenAI har begrensninger på tokens per minutt (TPM) og requests per minutt (RPM) per deployment, og én enkelt instans vil sjelden dekke behovene til en hel organisasjon. Ved å distribuere trafikk over flere instanser -- gjerne i ulike regioner -- kan organisasjoner øke total kapasitet, forbedre tilgjengelighet og optimalisere kostnader.
|
|
|
|
Azure API Management (APIM) tilbyr innebygd backend pool-funksjonalitet som gjør dette uten egenutviklet kode. Backend pools støtter round-robin, weighted, priority-basert og session-aware lastbalansering, kombinert med circuit breaker for automatisk failover. For norsk offentlig sektor er dette spesielt relevant: flere etater kan dele infrastruktur, mens Provisioned Throughput Units (PTU) prioriteres for å maksimere investert kapasitet.
|
|
|
|
Det er viktig å forstå at APIM-lastbalansering er approksimasjon: ulike gateway-instanser synkroniserer ikke state seg imellom. Dette betyr at vektede fordelinger er omtrentlige, ikke eksakte. For de fleste AI-brukstilfeller er dette akseptabelt, da Azure OpenAI selv håndterer throttling med 429-responser og Retry-After headers.
|
|
|
|
---
|
|
|
|
## Backend Pool-konsepter
|
|
|
|
### Hva er en backend pool?
|
|
|
|
En backend pool i APIM er en samling av backend-tjenester som gatewayen behandler som én logisk enhet for lastbalansering. For Azure OpenAI betyr dette at flere OpenAI-instanser (potensielt i ulike regioner, med ulike deployment-typer) grupperes bak ett endepunkt.
|
|
|
|
| Egenskap | Verdi |
|
|
|----------|-------|
|
|
| Maks backends per pool | 30 |
|
|
| Synkronisering mellom gateway-instanser | Nei (approksimasjon) |
|
|
| Session awareness | Ja (cookie-basert) |
|
|
| Health checking | Via circuit breaker |
|
|
| Deployment-modell | Bicep, ARM, REST API, Portal |
|
|
|
|
### Backend-registrering
|
|
|
|
Hver backend i poolen registreres med URL, autentisering og valgfrie metadata:
|
|
|
|
```xml
|
|
<!-- Policy: Rut til backend pool -->
|
|
<set-backend-service backend-id="openai-pool" />
|
|
```
|
|
|
|
---
|
|
|
|
## Load Balancing-strategier
|
|
|
|
### Strategi 1: Round-Robin
|
|
|
|
Fordeler requests jevnt mellom alle backends i poolen.
|
|
|
|
```
|
|
Request 1 → Backend A (Norway East)
|
|
Request 2 → Backend B (Sweden Central)
|
|
Request 3 → Backend C (West Europe)
|
|
Request 4 → Backend A (Norway East) ← syklusen gjentas
|
|
```
|
|
|
|
**Bruk når:**
|
|
- Alle instanser har lik kapasitet (samme TPM-allokering)
|
|
- Ingen preferanse for spesifikke regioner
|
|
- Enkel konfigurasjon er prioritert
|
|
|
|
**Bicep:**
|
|
|
|
```bicep
|
|
resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-pool'
|
|
properties: {
|
|
type: 'Pool'
|
|
pool: {
|
|
services: [
|
|
{
|
|
id: '/backends/openai-norwayeast'
|
|
}
|
|
{
|
|
id: '/backends/openai-swedencentral'
|
|
}
|
|
{
|
|
id: '/backends/openai-westeurope'
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Strategi 2: Weighted (vektet)
|
|
|
|
Fordeler requests basert på tildelte vekter. Nyttig når backends har ulik kapasitet.
|
|
|
|
```
|
|
Vekter: A=3, B=2, C=1 (totalt 6)
|
|
→ A mottar ~50% av trafikk
|
|
→ B mottar ~33% av trafikk
|
|
→ C mottar ~17% av trafikk
|
|
```
|
|
|
|
**Bruk når:**
|
|
- Backends har ulik TPM-allokering
|
|
- Blue-green deployment med gradvis trafikkskift
|
|
- Ulike pricing-modeller (PTU vs. pay-as-you-go)
|
|
|
|
**Bicep:**
|
|
|
|
```bicep
|
|
resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-pool-weighted'
|
|
properties: {
|
|
type: 'Pool'
|
|
pool: {
|
|
services: [
|
|
{
|
|
id: '/backends/openai-norwayeast-ptu'
|
|
weight: 5
|
|
priority: 1
|
|
}
|
|
{
|
|
id: '/backends/openai-swedencentral-paygo'
|
|
weight: 3
|
|
priority: 1
|
|
}
|
|
{
|
|
id: '/backends/openai-westeurope-paygo'
|
|
weight: 2
|
|
priority: 1
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Strategi 3: Priority-Based (anbefalt for AI)
|
|
|
|
Organiserer backends i prioritetsgrupper. Lavere prioritetsnummer = høyere prioritet. Backends i lavere prioritetsgrupper brukes kun når alle backends i høyere grupper er utilgjengelige (circuit breaker utløst).
|
|
|
|
```
|
|
Priority 1: PTU-instanser (fast pris, utnytt først)
|
|
├── openai-norwayeast-ptu (weight: 3)
|
|
└── openai-swedencentral-ptu (weight: 2)
|
|
|
|
Priority 2: Pay-as-you-go fallback
|
|
├── openai-westeurope-paygo (weight: 1)
|
|
└── openai-eastus-paygo (weight: 1)
|
|
```
|
|
|
|
**Typisk scenario for norsk offentlig sektor:**
|
|
|
|
| Prioritet | Deployment-type | Region | Begrunnelse |
|
|
|-----------|-----------------|--------|-------------|
|
|
| 1 | PTU | Norway East | Datasuverenitet + fast pris, bruk først |
|
|
| 1 | PTU | Sweden Central | Nær-region redundans |
|
|
| 2 | Pay-as-you-go | West Europe | Spillover ved høy last |
|
|
| 3 | Pay-as-you-go | East US | Nødfallback ved regional utfall |
|
|
|
|
**Bicep:**
|
|
|
|
```bicep
|
|
resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-pool-priority'
|
|
properties: {
|
|
type: 'Pool'
|
|
pool: {
|
|
services: [
|
|
{
|
|
id: '/backends/openai-norwayeast-ptu'
|
|
weight: 3
|
|
priority: 1
|
|
}
|
|
{
|
|
id: '/backends/openai-swedencentral-ptu'
|
|
weight: 2
|
|
priority: 1
|
|
}
|
|
{
|
|
id: '/backends/openai-westeurope-paygo'
|
|
weight: 1
|
|
priority: 2
|
|
}
|
|
{
|
|
id: '/backends/openai-eastus-paygo'
|
|
weight: 1
|
|
priority: 3
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Strategi 4: Session-Aware
|
|
|
|
Sikrer at alle requests fra samme bruker-sesjon rutes til samme backend. Kritisk for Azure OpenAI Assistants API der thread state er bundet til en spesifikk instans.
|
|
|
|
```
|
|
Sesjon 1: Bruker A ──cookie──► Backend A (alle requests i sesjonen)
|
|
Sesjon 2: Bruker B ──cookie──► Backend B (alle requests i sesjonen)
|
|
Sesjon 3: Bruker C ──cookie──► Backend A (ny sesjon, tilfeldig valgt)
|
|
```
|
|
|
|
**Bruk når:**
|
|
- Assistants API (thread state)
|
|
- Chat-applikasjoner med stateful backends
|
|
- Når backend cacher bruker-kontekst
|
|
|
|
**Bicep:**
|
|
|
|
```bicep
|
|
resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-pool-session'
|
|
properties: {
|
|
type: 'Pool'
|
|
pool: {
|
|
services: [
|
|
{
|
|
id: '/backends/openai-norwayeast'
|
|
weight: 1
|
|
priority: 1
|
|
}
|
|
{
|
|
id: '/backends/openai-swedencentral'
|
|
weight: 1
|
|
priority: 1
|
|
}
|
|
]
|
|
sessionAffinity: {
|
|
type: 'Cookie'
|
|
cookieName: 'apim-session-id'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Cookie-håndtering for klienter:**
|
|
Klienter MÅ lagre `Set-Cookie`-headeren fra APIM og sende den tilbake i påfølgende requests for å opprettholde sesjonsaffinitet.
|
|
|
|
---
|
|
|
|
## Individual Backend-konfigurasjon
|
|
|
|
### Registrere en Azure OpenAI backend
|
|
|
|
```bicep
|
|
resource openaiBackend 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-norwayeast-ptu'
|
|
properties: {
|
|
url: 'https://aoai-norwayeast.openai.azure.com/openai'
|
|
protocol: 'http'
|
|
description: 'Azure OpenAI PTU deployment i Norway East'
|
|
circuitBreaker: {
|
|
rules: [
|
|
{
|
|
name: 'openai-circuit-breaker'
|
|
failureCondition: {
|
|
count: 3
|
|
interval: 'PT1M'
|
|
statusCodeRanges: [
|
|
{ min: 429, max: 429 }
|
|
{ min: 500, max: 599 }
|
|
]
|
|
}
|
|
tripDuration: 'PT10S'
|
|
acceptRetryAfter: true
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Autentisering via Managed Identity
|
|
|
|
```xml
|
|
<policies>
|
|
<inbound>
|
|
<set-backend-service backend-id="openai-pool-priority" />
|
|
<authentication-managed-identity
|
|
resource="https://cognitiveservices.azure.com/" />
|
|
</inbound>
|
|
</policies>
|
|
```
|
|
|
|
**RBAC-konfigurasjon:**
|
|
|
|
```bicep
|
|
// Grant Cognitive Services User role to APIM managed identity
|
|
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
|
|
scope: openaiResource
|
|
name: guid(apim.id, openaiResource.id, 'cognitive-services-user')
|
|
properties: {
|
|
roleDefinitionId: subscriptionResourceId(
|
|
'Microsoft.Authorization/roleDefinitions',
|
|
'a97b65f3-24c7-4388-baec-2e87135dc908' // Cognitive Services User
|
|
)
|
|
principalId: apim.identity.principalId
|
|
principalType: 'ServicePrincipal'
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Deployment Slot Selection
|
|
|
|
### Routing til ulike modell-deployments
|
|
|
|
Når backends har ulike deployment-navn (f.eks. `gpt-4o` i en region, `gpt4-turbo` i en annen), kan APIM-policies transformere URL-en:
|
|
|
|
```xml
|
|
<policies>
|
|
<inbound>
|
|
<set-backend-service backend-id="openai-pool-priority" />
|
|
|
|
<!-- Override deployment name basert på backend-region -->
|
|
<choose>
|
|
<when condition="@(context.Backend?.AzureRegion == "norwayeast")">
|
|
<rewrite-uri template="/deployments/gpt-4o/chat/completions" />
|
|
</when>
|
|
<when condition="@(context.Backend?.AzureRegion == "swedencentral")">
|
|
<rewrite-uri template="/deployments/gpt4-turbo/chat/completions" />
|
|
</when>
|
|
</choose>
|
|
|
|
<authentication-managed-identity
|
|
resource="https://cognitiveservices.azure.com/" />
|
|
</inbound>
|
|
</policies>
|
|
```
|
|
|
|
### Modell-versjonshåndtering
|
|
|
|
```xml
|
|
<!-- Sett api-version basert på backend -->
|
|
<set-query-parameter name="api-version" exists-action="override">
|
|
<value>2024-10-21</value>
|
|
</set-query-parameter>
|
|
```
|
|
|
|
---
|
|
|
|
## Regional Distribution
|
|
|
|
### Topologi 1: Single-Region APIM, Multi-Region Backends
|
|
|
|
```
|
|
APIM (Norway East)
|
|
│
|
|
┌────────┼────────┐
|
|
▼ ▼ ▼
|
|
OpenAI OpenAI OpenAI
|
|
(Norway East) (Sweden C.) (West EU)
|
|
Priority 1 Priority 1 Priority 2
|
|
```
|
|
|
|
**Fordeler:** Enkel arkitektur, ett kontrollpunkt
|
|
**Ulemper:** APIM er single point of failure, cross-region latens
|
|
|
|
### Topologi 2: Multi-Region APIM, Regional Backends
|
|
|
|
```
|
|
Client → DNS (latency-based routing)
|
|
│
|
|
┌────────┴────────┐
|
|
▼ ▼
|
|
APIM Gateway APIM Gateway
|
|
(Norway East) (Sweden Central)
|
|
│ │
|
|
▼ ▼
|
|
OpenAI OpenAI
|
|
(Norway East) (Sweden Central)
|
|
```
|
|
|
|
**Fordeler:** Ingen regional single point of failure, lav latens
|
|
**Ulemper:** Krever APIM Premium, dyrere
|
|
|
|
**Bicep for multi-region APIM:**
|
|
|
|
```bicep
|
|
resource apim 'Microsoft.ApiManagement/service@2023-09-01-preview' = {
|
|
name: 'apim-ai-gateway'
|
|
location: 'norwayeast'
|
|
sku: {
|
|
name: 'Premium'
|
|
capacity: 1
|
|
}
|
|
properties: {
|
|
additionalLocations: [
|
|
{
|
|
location: 'swedencentral'
|
|
sku: {
|
|
name: 'Premium'
|
|
capacity: 1
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Topologi 3: Active-Active med Active-Passive Backends
|
|
|
|
Kombinerer regional redundans med kostnadsoptimalisering:
|
|
|
|
```
|
|
APIM Gateway (Norway East)
|
|
├── Active: OpenAI PTU (Norway East) Priority 1
|
|
├── Passive: OpenAI PAYGO (Norway East) Priority 2
|
|
└── Cross: OpenAI PAYGO (Sweden C.) Priority 3 (kun ved regional feil)
|
|
|
|
APIM Gateway (Sweden Central)
|
|
├── Active: OpenAI PTU (Sweden C.) Priority 1
|
|
├── Passive: OpenAI PAYGO (Sweden C.) Priority 2
|
|
└── Cross: OpenAI PAYGO (Norway East) Priority 3
|
|
```
|
|
|
|
**Regional policy routing:**
|
|
|
|
```xml
|
|
<choose>
|
|
<when condition="@(context.Deployment.Region == "Norway East")">
|
|
<set-backend-service backend-id="pool-norwayeast" />
|
|
</when>
|
|
<when condition="@(context.Deployment.Region == "Sweden Central")">
|
|
<set-backend-service backend-id="pool-swedencentral" />
|
|
</when>
|
|
</choose>
|
|
```
|
|
|
|
---
|
|
|
|
## Throttling og Retry-håndtering
|
|
|
|
### Smart Load Balancing
|
|
|
|
Når en backend returnerer 429 (Too Many Requests), skal gatewayen:
|
|
1. Lese `Retry-After`-headeren
|
|
2. Markere backend som utilgjengelig via circuit breaker
|
|
3. Umiddelbart retry til neste tilgjengelige backend i poolen
|
|
4. IKKE vente (ingen delay mellom retries til ulike backends)
|
|
|
|
```xml
|
|
<policies>
|
|
<inbound>
|
|
<set-backend-service backend-id="openai-pool-priority" />
|
|
</inbound>
|
|
|
|
<backend>
|
|
<retry condition="@(context.Response.StatusCode == 429)"
|
|
count="3"
|
|
interval="0"
|
|
first-fast-retry="true">
|
|
<set-backend-service backend-id="openai-pool-priority" />
|
|
</retry>
|
|
</backend>
|
|
</policies>
|
|
```
|
|
|
|
### PTU + PAYGO Spillover-mønster
|
|
|
|
Det mest vanlige mønsteret for kostnadsoptimalisering:
|
|
|
|
```
|
|
Normal trafikk:
|
|
All trafikk → PTU (Priority 1, fast pris)
|
|
|
|
Ved throttling (PTU kapasitet brukt opp):
|
|
Circuit breaker utløst på PTU
|
|
Trafikk → PAYGO (Priority 2, pay-per-token)
|
|
|
|
Etter PTU recovery:
|
|
Circuit breaker reset
|
|
Trafikk → PTU (Priority 1, tilbake til fast pris)
|
|
```
|
|
|
|
| Fase | Backend | Kostnad | Latens |
|
|
|------|---------|---------|--------|
|
|
| Normal | PTU | Fast (forutsigbar) | Lav (garantert) |
|
|
| Spillover | PAYGO | Variabel (høyere) | Variabel |
|
|
| Recovery | PTU | Fast | Lav |
|
|
|
|
---
|
|
|
|
## Komplett Bicep-eksempel
|
|
|
|
```bicep
|
|
@description('Komplett AI Gateway med priority-based load balancing')
|
|
|
|
param location string = 'norwayeast'
|
|
param environment string = 'prod'
|
|
|
|
// Azure OpenAI instances
|
|
resource aoaiNorway 'Microsoft.CognitiveServices/accounts@2024-10-01' existing = {
|
|
name: 'aoai-norwayeast-${environment}'
|
|
}
|
|
|
|
resource aoaiSweden 'Microsoft.CognitiveServices/accounts@2024-10-01' existing = {
|
|
name: 'aoai-swedencentral-${environment}'
|
|
}
|
|
|
|
// APIM Instance
|
|
resource apim 'Microsoft.ApiManagement/service@2023-09-01-preview' = {
|
|
name: 'apim-ai-gw-${environment}'
|
|
location: location
|
|
sku: {
|
|
name: 'StandardV2'
|
|
capacity: 1
|
|
}
|
|
identity: {
|
|
type: 'SystemAssigned'
|
|
}
|
|
properties: {
|
|
publisherEmail: 'ai-team@example.no'
|
|
publisherName: 'AI Gateway'
|
|
}
|
|
}
|
|
|
|
// Backend: Norway East PTU
|
|
resource backendNorwayPTU 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-norwayeast-ptu'
|
|
properties: {
|
|
url: '${aoaiNorway.properties.endpoint}openai'
|
|
protocol: 'http'
|
|
circuitBreaker: {
|
|
rules: [
|
|
{
|
|
name: 'throttle-protection'
|
|
failureCondition: {
|
|
count: 3
|
|
interval: 'PT1M'
|
|
statusCodeRanges: [
|
|
{ min: 429, max: 429 }
|
|
{ min: 500, max: 599 }
|
|
]
|
|
}
|
|
tripDuration: 'PT10S'
|
|
acceptRetryAfter: true
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
// Backend: Sweden Central PAYGO
|
|
resource backendSwedenPAYGO 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-swedencentral-paygo'
|
|
properties: {
|
|
url: '${aoaiSweden.properties.endpoint}openai'
|
|
protocol: 'http'
|
|
circuitBreaker: {
|
|
rules: [
|
|
{
|
|
name: 'throttle-protection'
|
|
failureCondition: {
|
|
count: 3
|
|
interval: 'PT1M'
|
|
statusCodeRanges: [
|
|
{ min: 429, max: 429 }
|
|
{ min: 500, max: 599 }
|
|
]
|
|
}
|
|
tripDuration: 'PT10S'
|
|
acceptRetryAfter: true
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
// Backend Pool with priority-based routing
|
|
resource backendPool 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
|
|
parent: apim
|
|
name: 'openai-pool'
|
|
properties: {
|
|
type: 'Pool'
|
|
pool: {
|
|
services: [
|
|
{
|
|
id: '/backends/${backendNorwayPTU.name}'
|
|
weight: 3
|
|
priority: 1
|
|
}
|
|
{
|
|
id: '/backends/${backendSwedenPAYGO.name}'
|
|
weight: 1
|
|
priority: 2
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Overvåking og feilsøking
|
|
|
|
### Identifisere hvilken backend som serverte request
|
|
|
|
```xml
|
|
<outbound>
|
|
<set-header name="X-Backend-Id" exists-action="override">
|
|
<value>@(context.Backend?.Id ?? "unknown")</value>
|
|
</set-header>
|
|
<set-header name="X-Backend-Type" exists-action="override">
|
|
<value>@(context.Backend?.Type ?? "unknown")</value>
|
|
</set-header>
|
|
</outbound>
|
|
```
|
|
|
|
### KQL for load balancing-distribusjon
|
|
|
|
```kusto
|
|
ApiManagementGatewayLogs
|
|
| where OperationId == "ChatCompletions_Create"
|
|
| extend backendUrl = tostring(BackendUrl)
|
|
| summarize RequestCount = count() by backendUrl, bin(TimeGenerated, 1h)
|
|
| render columnchart
|
|
```
|
|
|
|
---
|
|
|
|
## For arkitekten
|
|
|
|
- Priority-based load balancing med PTU som Priority 1 og PAYGO som Priority 2 er det anbefalte mønsteret for enterprise AI-arkitekturer -- det maksimerer utnyttelsen av forhåndskjøpt kapasitet og faller automatisk tilbake til pay-per-use ved behov.
|
|
- Backend pools er approksimerte: ulike gateway-instanser synkroniserer ikke, så vektede fordelinger er omtrentlige. For AI-workloads er dette akseptabelt fordi Azure OpenAI selv håndterer throttling med 429/Retry-After.
|
|
- Session awareness er kritisk for Assistants API og chat-applikasjoner med stateful backends -- aktiver dette med cookie-basert sesjonsaffinitet i pool-konfigurasjonen.
|
|
- For norsk offentlig sektor med datasuverenitetskrav: prioriter Norway East og Sweden Central, bruk private endpoints, og vurder om cross-region failover til EU-regioner er akseptabelt under gjeldende regelverk.
|
|
- Kombiner alltid backend pools med circuit breaker (inkludert `acceptRetryAfter: true`) for intelligent failover ved 429-responser fra Azure OpenAI.
|