KB-currency refresh (medium priority, 2026-06-19) via /architect:kb-update. 74 medium-prioritets filer re-verifisert mot Microsoft Learn (MCP) — delegert til 15 parallelle Opus-subagenter (3 bølger) gruppert etter delt kilde, med disjunkte fil-sett. Verifisert i hovedkontekst (scope-sjekk + diff-review av de faktatunge gruppene + tester). Hovedendringer (faktuelle korreksjoner + currency): - Azure AI Search semantic ranker: TILGJENGELIG PÅ ALLE TIERS (også Free/Basic m/ gratis månedlig kvote) — gammel KB sa feilaktig "kun S1+". Korrigert i tier-tabell, anti-patterns og beslutningstabell (azure-ai-search-setup). - APIM score-threshold = DISTANSE (lavere = strengere): tuning-tabellen i rag-caching-optimization hadde retningen baklengs — invertert til korrekt. - Agentic retrieval GA/preview-nyanse presisert (hovedkontekst-korreksjon mot agentic-retrieval-how-to-migrate): GA via REST 2026-04-01 returnerer EKSTRAKTIV grounding (references + activity), IKKE syntetiserte svar. Answer synthesis, ikke-minimal reasoning effort (LLM query planning) og multi-turn messages forblir preview (2026-05-01-preview). Subagent hadde overforenklet til "hele kjernepipelinen GA"; rettet i agentic-rag-patterns + citation-tracking. - Copilot Studio modell-tabeller (platforms/copilot-studio): fjernet Claude Opus 4.5 + GPT-5.2 (borte fra kilde), lagt til Claude Sonnet 4.6/Opus 4.6 (GA), Opus 4.7 + Mistral Medium 3.5 (experimental); GPT-5 Reasoning/Auto = preview; A2A GA (apr 2026). - Computer Use (CUA): Copilot Studio GA 2026-05-07; 4 modeller m/ tier/status (OpenAI CUA + Sonnet 4.5 GA, Sonnet 4.6 + Opus 4.6 experimental); 5 credits/ steg standard, 15 premium; US-only region-krav FJERNET i GA-dok; Cloud PC pool + Hosted browser + bring-your-own-machine. - Azure AI Search REST API-versjoner bumpet: 2025-09-01 -> 2026-04-01 (stabil), 2025-11-01-preview -> 2026-05-01-preview (hybrid-search, rag-security-rbac, chunking). - Power Automate-integrasjon: trigger "Run a flow from Copilot" -> "When an agent calls the flow"; App Service innebygd MCP (preview) lagt til. - M365 Copilot-manifest v1.26 -> v1.28 (GA, mai) / v1.29 dokumentert (juni); "Tenant graph grounding" -> "Work IQ". - Speech fast transcription 2t/300MB -> 5t/500MB; multilingual 14 -> 15 locales (+ pt-BR). Content Understanding reasoning preview -> GA (v1.0, 2025-11-01). - Security Copilot E5 -> E5+E7. Død Databricks-URL ci-cd/best-practices -> ci-cd/flows. Prompt Flow retirement (2027-04-20 -> MAF) notert der den presenteres som go-forward. Gateway-topologi-tabell-feil rettet. - Alle 74 Last updated -> 2026-06-19. Discovery ikke kjørt (historisk kun Databricks-støy) -> 389-telling uendret, ingen resync. validate 239 PASS, kb-integrity 115/115 (262 orphan-warnings uendret), gitleaks clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01REiKFhP4w6xGXXqWKpPCJJ
16 KiB
Connection Pooling Patterns
Last updated: 2026-06-19 | Verified: MCP 2026-06-19 Status: GA Category: Performance & Scalability
Introduksjon
Connection pooling er en kritisk ytelsesoptimalisering for applikasjoner som kommuniserer med Azure AI Services. Hver HTTP-forbindelse til Azure OpenAI eller andre AI-endepunkter krever TCP-håndtrykk og eventuelt TLS-forhandling, noe som legger til betydelig latens per forespørsel. Uten connection pooling opprettes og lukkes forbindelser for hver eneste forespørsel, noe som fører til port-utmattelse, økt responstid og unødvendig CPU-bruk.
I .NET-økosystemet er HttpClient den sentrale klassen for HTTP-kommunikasjon, og Microsofts offisielle retningslinjer er tydelige: bruk én statisk HttpClient-instans per logisk klient, eller bruk IHttpClientFactory for å håndtere DNS-endringer og connection lifecycle. Azure OpenAI SDK-ene (både Python og C#) håndterer connection pooling internt, men korrekt konfigurasjon er fortsatt nødvendig for optimal ytelse.
For norsk offentlig sektor der AI-tjenester typisk nås via private endpoints og ofte går gjennom Azure API Management, er connection pooling spesielt viktig. Nettverkskjeden (klient → APIM → Private Endpoint → Azure OpenAI) multipliserer latens-kostnaden av nye forbindelser, og korrekt pooling kan redusere p50-latens med 30-50 ms per forespørsel.
Kjernekomponenter
| Komponent | Formål | Teknologi |
|---|---|---|
| HttpClient / HttpClientFactory | HTTP connection management i .NET | System.Net.Http |
| SocketsHttpHandler | Underliggende socket-håndtering med pool | .NET 6+ |
| aiohttp.ClientSession | Asynkron HTTP med connection pool i Python | aiohttp |
| httpx.AsyncClient | Moderne asynkron HTTP-klient med pool | httpx |
| Azure OpenAI SDK | Innebygd connection management | azure-ai-openai |
| Azure API Management | Gateway med backend connection pooling | Azure APIM |
Pool Sizing-strategier
Beregning av optimal pool-størrelse
Pool-størrelsen bør baseres på forventet concurrent request-volum og responstid fra backend-tjenesten.
# Beregn optimal pool-størrelse
# Formel: pool_size = concurrent_requests * avg_response_time_seconds / target_utilization
def calculate_pool_size(
concurrent_users: int,
avg_response_time_ms: float,
requests_per_user_per_second: float = 1.0,
target_utilization: float = 0.75
) -> int:
"""Calculate optimal connection pool size for AI workloads."""
concurrent_requests = concurrent_users * requests_per_user_per_second
avg_response_time_s = avg_response_time_ms / 1000
# Connections needed = concurrent requests * time each holds a connection
connections_needed = concurrent_requests * avg_response_time_s
# Add headroom for bursts
pool_size = int(connections_needed / target_utilization)
# Azure OpenAI typical ranges
return max(pool_size, 10) # Minimum 10 connections
# Eksempel: 50 samtidige brukere, 800ms avg responstid
optimal = calculate_pool_size(
concurrent_users=50,
avg_response_time_ms=800,
requests_per_user_per_second=0.5
)
print(f"Anbefalt pool-størrelse: {optimal}") # ~27 connections
.NET HttpClientFactory-konfigurasjon
// Program.cs - Optimal HttpClient-konfigurasjon for Azure OpenAI
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http;
var builder = WebApplication.CreateBuilder(args);
// Registrer named HttpClient for Azure OpenAI
builder.Services.AddHttpClient("AzureOpenAI", client =>
{
client.BaseAddress = new Uri(
builder.Configuration["AzureOpenAI:Endpoint"]!);
client.DefaultRequestHeaders.Add("api-key",
builder.Configuration["AzureOpenAI:ApiKey"]!);
client.Timeout = TimeSpan.FromSeconds(120);
})
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
// Pool-konfigurasjon
MaxConnectionsPerServer = 50, // Maks connections per host
PooledConnectionLifetime = TimeSpan.FromMinutes(5), // DNS refresh
PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2),
// Keep-alive
KeepAlivePingPolicy = HttpKeepAlivePingPolicy.WithActiveRequests,
KeepAlivePingDelay = TimeSpan.FromSeconds(30),
KeepAlivePingTimeout = TimeSpan.FromSeconds(10),
// Performance
EnableMultipleHttp2Connections = true,
AutomaticDecompression = System.Net.DecompressionMethods.GZip
})
.SetHandlerLifetime(TimeSpan.FromMinutes(10)); // Handler rotation
// Registrer Azure OpenAI-klient med pooled HttpClient
builder.Services.AddSingleton(sp =>
{
var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient("AzureOpenAI");
return new Azure.AI.OpenAI.AzureOpenAIClient(
new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!),
new Azure.AzureKeyCredential(
builder.Configuration["AzureOpenAI:ApiKey"]!));
});
Keep-alive-konfigurasjon
HTTP/2 Multiplexing
Azure OpenAI støtter HTTP/2, som muliggjør multipleksing av flere forespørsler over én enkelt TCP-forbindelse:
// HTTP/2 multiplexing for Azure OpenAI
var handler = new SocketsHttpHandler
{
// Aktiver HTTP/2 med multipleksing
EnableMultipleHttp2Connections = true,
// Keep-alive for langvarige streams
KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always,
KeepAlivePingDelay = TimeSpan.FromSeconds(15),
KeepAlivePingTimeout = TimeSpan.FromSeconds(5),
// Connection lifecycle
PooledConnectionLifetime = TimeSpan.FromMinutes(10),
PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2),
MaxConnectionsPerServer = 100
};
var client = new HttpClient(handler)
{
DefaultRequestVersion = HttpVersion.Version20,
DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower
};
Python aiohttp Session Management
import aiohttp
import asyncio
from openai import AsyncAzureOpenAI
async def create_optimized_session() -> aiohttp.ClientSession:
"""Create an optimized aiohttp session for Azure OpenAI."""
connector = aiohttp.TCPConnector(
limit=100, # Total connection pool size
limit_per_host=50, # Max connections per host
ttl_dns_cache=300, # DNS cache TTL i sekunder
keepalive_timeout=30, # Keep-alive timeout
enable_cleanup_closed=True,
force_close=False # Gjenbruk connections
)
timeout = aiohttp.ClientTimeout(
total=120, # Total timeout
connect=10, # Connection timeout
sock_read=60 # Read timeout
)
return aiohttp.ClientSession(
connector=connector,
timeout=timeout,
headers={"Connection": "keep-alive"}
)
# Bruk med Azure OpenAI Python SDK
async def create_pooled_openai_client() -> AsyncAzureOpenAI:
"""Create Azure OpenAI client with optimized connection pooling."""
import httpx
transport = httpx.AsyncHTTPTransport(
retries=3,
limits=httpx.Limits(
max_connections=100,
max_keepalive_connections=50,
keepalive_expiry=30
)
)
http_client = httpx.AsyncClient(
transport=transport,
timeout=httpx.Timeout(120.0, connect=10.0)
)
return AsyncAzureOpenAI(
azure_endpoint="https://my-aoai.openai.azure.com",
api_key="...",
api_version="2024-10-21",
http_client=http_client
)
Connection Recycling
Håndtering av DNS-endringer
Når Azure OpenAI-endepunkter er bak Traffic Manager eller Azure Front Door, endres IP-adresser regelmessig. Connection pooling må balansere gjenbruk med DNS-fornyelse:
// Connection recycling pattern
public class ConnectionRecyclingConfig
{
// PooledConnectionLifetime: Tvinger nye DNS-oppslag
// Sett lavere enn DNS TTL for failover-scenarier
public TimeSpan PooledConnectionLifetime { get; set; }
= TimeSpan.FromMinutes(5);
// PooledConnectionIdleTimeout: Fjern ubrukte connections
public TimeSpan PooledConnectionIdleTimeout { get; set; }
= TimeSpan.FromMinutes(2);
// Handler lifetime for IHttpClientFactory
// Roterer hele handleren — nye connections med ny DNS
public TimeSpan HandlerLifetime { get; set; }
= TimeSpan.FromMinutes(10);
}
// Anti-pattern: ALDRI gjør dette
// ❌ var client = new HttpClient(); // Ny for hver forespørsel
// ❌ using var client = new HttpClient(); // Disponeres for tidlig
// Korrekt pattern: Singleton eller factory
// ✅ Statisk HttpClient med SocketsHttpHandler
// ✅ IHttpClientFactory i DI
Load Distribution
Round-robin over multiple Azure OpenAI-instanser
import asyncio
import random
from dataclasses import dataclass, field
from typing import Optional
from openai import AsyncAzureOpenAI
@dataclass
class AzureOpenAIBackend:
endpoint: str
api_key: str
priority: int = 1
is_healthy: bool = True
retry_after: Optional[float] = None
client: Optional[AsyncAzureOpenAI] = field(default=None, repr=False)
class ConnectionPoolLoadBalancer:
"""Load balancer with dedicated connection pools per backend."""
def __init__(self, backends: list[AzureOpenAIBackend]):
self.backends = backends
# Separat connection pool per backend
for backend in self.backends:
backend.client = AsyncAzureOpenAI(
azure_endpoint=backend.endpoint,
api_key=backend.api_key,
api_version="2024-10-21",
max_retries=0 # Vi håndterer retry selv
)
def _select_backend(self) -> AzureOpenAIBackend:
"""Select backend by priority, then random among same priority."""
import time
# Filtrer friske backends
available = [
b for b in self.backends
if b.is_healthy or (
b.retry_after and time.time() > b.retry_after
)
]
if not available:
available = self.backends # Fallback til alle
# Velg laveste prioritet (høyest prioritet)
min_priority = min(b.priority for b in available)
candidates = [b for b in available if b.priority == min_priority]
return random.choice(candidates)
async def chat_completion(self, messages: list, **kwargs):
"""Route request to best available backend."""
import time
for attempt in range(len(self.backends)):
backend = self._select_backend()
try:
response = await backend.client.chat.completions.create(
messages=messages, **kwargs
)
backend.is_healthy = True
return response
except Exception as e:
if hasattr(e, 'status_code') and e.status_code == 429:
retry_after = getattr(e, 'retry_after', 10)
backend.retry_after = time.time() + retry_after
backend.is_healthy = False
elif hasattr(e, 'status_code') and e.status_code >= 500:
backend.is_healthy = False
else:
raise
raise Exception("All backends exhausted")
Azure API Management som Connection Pooling-lag (oppdatert 2026-06-19)
APIM håndterer backend connection pooling mot Azure OpenAI, noe som avlaster klientsiden:
APIM Backend Pool-konfigurasjon
<!-- APIM: Backend pool med automatisk connection management -->
<policies>
<inbound>
<base />
<!-- APIM gjenbruker backend-connections automatisk via intern pool -->
<!-- Klientene ser APIM som et enkelt endepunkt -->
<set-backend-service id="aoai-pool" backend-id="aoai-norway-backend" />
<!-- Legg til correlation ID for tracing -->
<set-header name="x-correlation-id" exists-action="skip">
<value>@(context.RequestId)</value>
</set-header>
</inbound>
<backend>
<retry condition="@(context.Response.StatusCode == 429 || context.Response.StatusCode >= 500)"
count="3" interval="0" first-fast-retry="true">
<!-- APIM håndterer retry mot backend-pool -->
<forward-request timeout="120" />
</retry>
</backend>
<outbound>
<!-- Eksponer backend latens-metrikk til klient -->
<set-header name="x-backend-latency-ms" exists-action="override">
<value>@(context.Elapsed.TotalMilliseconds.ToString())</value>
</set-header>
</outbound>
</policies>
Backend-konfigurasjoner i APIM (4 topologier)
Microsoft anbefaler disse mønstrene for APIM connection pooling mot Azure OpenAI:
- Single backend: Én APIM → én Azure OpenAI (enkelt, begrenset kvote)
- Multi-backend single region: APIM med weighted round-robin mellom Azure OpenAI-instanser
- Multi-subscription: Separate Azure OpenAI-instanser i ulike subscriptions for kvote-skalering
- Multi-region: APIM i flere regioner, each med regionale backends
Klientene trenger aldri kjenne til antallet backends — APIM håndterer routing transparent.
Norsk offentlig sektor
Connection pooling har spesielle hensyn for norsk offentlig sektor:
- Data residency: Alle connections må gå via regioner som oppfyller Schrems II-kravene. Ved bruk av Azure Norway East som primær region, konfigurer
PooledConnectionLifetimekort nok til å håndtere failover til Sweden Central. - Private endpoints: Connection pools som bruker Private Link har andre DNS-oppløsningsmønstre. Konfigurer
ttl_dns_cachei Python ellerPooledConnectionLifetimei .NET til å matche DNS TTL for privatelink-soner (typisk 10 sekunder). - NSMs grunnprinsipper: Logging av connection pool-metrikker (aktive connections, pool hits/misses, connection errors) er påkrevd for å oppfylle krav om overvåking av nettverkstrafikk.
- Anskaffelsesreglement: Ved bruk av tredjepartsbiblioteker for connection pooling, verifiser at de er godkjent for bruk i offentlig sektor (åpen kildekode med akseptabel lisens).
Beslutningsrammeverk
| Scenario | Anbefaling | Begrunnelse |
|---|---|---|
| Enkelttjeneste, lav trafikk (<10 RPS) | Statisk HttpClient med default pool | Enkel oppsett, tilstrekkelig ytelse |
| Enkelttjeneste, høy trafikk (>50 RPS) | HttpClientFactory med SocketsHttpHandler | DNS rotation, pool sizing, monitoring |
| Multi-region med failover | Separat pool per region + load balancer | Isolerer feil, støtter weighted routing |
| Via Azure APIM | APIM backend pool + klient-side pool | APIM håndterer backend-balansering |
| Streaming/SSE-respons | Dedikert pool med lange timeouts | Streaming holder connections åpne lenger |
| Azure Functions (serverless) | Static HttpClient i startup | Unngå cold start connection overhead |
Referanser
- Guidelines for using HttpClient — HttpClient best practices
- Pool HTTP connections with HttpClientFactory — ASP.NET performance
- Manage connections in Azure Functions — Serverless connection management
- Use a gateway in front of multiple Azure OpenAI deployments or instances — Multi-backend gateway patterns (Azure OpenAI i Foundry Models) — Verified (MCP 2026-06-19)
For Cosmo
- Bruk denne referansen når kunden rapporterer høy latens, port-utmattelse, eller timeout-feil mot Azure OpenAI — connection pooling er ofte root cause.
- Anbefal
IHttpClientFactoryfor .NET oghttpx.AsyncClientmedLimitsfor Python — aldri instansierHttpClientper forespørsel. - For multi-region AI-arkitekturer, opprett separate connection pools per region med individuelle health checks og retry-after tracking.
- Sett
PooledConnectionLifetimetil 2-5 minutter for å balansere DNS-fornyelse med connection gjenbruk — kortere for failover-scenarier. - Monitorer alltid
connections.active,connections.idleogpool.exhaustedmetrikker i Application Insights for å oppdage pool-problemer tidlig.