API Management
Welches Problem veranlasst mich also, eine API-Verwaltungslösung zu suchen? Wahrscheinlich stehen Sie vor den folgenden Herausforderungen:
- Skalierung: Ihre API oder APIs werden von vielen Clients in verschiedenen Regionen der Welt verwendet, und Sie müssen sicherstellen, dass sie verfügbar und reaktionsfähig ist.
- Sicherheit: Sie müssen sicherstellen, dass Ihre API sicher ist und nur autorisierte Clients darauf zugreifen können.
- Fehlerverwaltung: Sie müssen sicherstellen, dass Ihre API Fehler ordnungsgemäß verarbeiten kann.
- Überwachung: Sie müssen Ihre APIs überwachen, um sicherzustellen, dass sie wie erwartet ausgeführt wird.
- Resilienz: Sie müssen sicherstellen, dass Ihre API robust ist und Fehler ordnungsgemäß verarbeiten kann.
Für jede dieser Herausforderungen könnten Sie sich für eine Punktlösung entscheiden, aber das könnte schwierig zu handhaben sein. Bedenken Sie auch, dass Ihre APIs in verschiedenen technischen Stapeln erstellt werden könnten, wodurch die Lösungen für die oben genannten Herausforderungen es erforderlich machen könnten, dass Sie für jede API unterschiedliche Lösungen benötigen. Wenn Sie vor diesen Herausforderungen stehen, sollten Sie eine zentrale API-Verwaltungslösung wie Azure API Management in Betracht ziehen.
Sehen wir uns einige Herausforderungen genauer an, um zu sehen, wie eine zentrale API Management-Lösung wie Azure API Management Ihnen dabei helfen kann, sie zu meistern.
Infrastruktur als Code (Infrastructure-as-Code, IaC)
Es ist völlig in Ordnung, Ihre Azure-Ressourcen über das Azure-Portal zu erstellen, aber wenn Ihre Infrastruktur wächst, wird die Verwaltung schwieriger. Eines der Probleme besteht darin, dass Sie Ihre Infrastruktur nicht einfach in einer anderen Umgebung replizieren können.
Es ist auch schwierig, alle Änderungen zu verfolgen, die an Ihrer Infrastruktur vorgenommen werden. In dieser Situation kommt Infrastructure as Code (IaC) ins Spiel. IaC bedeutet, Ihre Infrastruktur mithilfe von Code zu verwalten. Um IaC auf Azure anzuwenden, haben Sie mehrere Möglichkeiten, eine davon ist Bicep. Bicep ist eine domänenspezifische Sprache (DSL) für die deklarative Bereitstellung von Azure-Ressourcen. Es ist eine hervorragende Möglichkeit, Ihre Cloudressourcen zu verwalten. Hier ist ein einfaches Beispiel von Bicep:
param location string = 'eastus'
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
name: 'mystorageaccount'
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
Im vorherigen Beispiel haben wir ein Speicherkonto mit Bicep definiert. Wir haben den Speicherort des Speicherkontos, die Art des Speicherkontos und die SKU (Lagerhaltungseinheit) definiert. Der Speicherort ist ein Parameter, den wir übergeben können, wenn wir die Bicep-Datei bereitstellen. Um die dargestellte Datei bereitzustellen, verwenden wir die Azure CLI wie folgt:
az deployment group create --resource-group myResourceGroup --template-file main.bicep
Mit dem vorherigen Befehl wird das Speicherkonto für die Ressourcengruppe myResourceGroup
bereitgestellt und die Bicep-Datei main.bicep
zum Erstellen der Ressourcen in der Datei verwendet.
Behandeln von Lasten über ein Lastenausgleichsmodul
Das Hinzufügen eines Lastenausgleichskonstrukts bietet sich an, wenn das Problem darin besteht, dass Ihre API von Anforderungen überfordert wird. Ein Lastenausgleichsmodul kann Ihnen dabei helfen, die Last über mehrere Instanzen Ihrer API zu verteilen.
Im Azure API Management-Dienst wird der Lastenausgleich implementiert, indem Sie ein Konzept definieren, das als Back-End bezeichnet wird. Die Idee ist, dass Sie viele Back-Ends einrichten, die Ihren API-Endpunkten entsprechen. Anschließend erstellen Sie ein Lastenausgleichsmodul, das die Last über diese Back-Ends verteilt. So sieht die Architektur aus:
In der vorherigen Architektur geschieht Folgendes:
- Vom Client wird eine Anforderung an die API Management-Instanz gesendet.
- Die Anforderung wird authentifiziert und autorisiert.
- Die Anforderung wird dann an den Lastenausgleich gesendet.
- Der Lastenausgleich verteilt die Anforderung an eines der Back-Ends (die ausgewählte Azure OpenAI-API ist fett formatiert).
Das Back-End verarbeitet die Anforderung und sendet eine Antwort an den Client zurück.
Definieren des Lastenausgleichsmoduls
Zum Einrichten eines Lastenausgleichs in Azure API Management müssen Sie die folgenden Komponenten ausführen:
- Back-Ends: ausreichend viele Back-Ends zum Verteilen der Last.
- Lastenausgleich: ein Lastenausgleichsmodul, das die Back-Ends enthält, über die Sie die Last verteilen möchten.
- Eine Richtlinie, die die eingehenden Anrufe an das Lastenausgleichsmodul leitet.
Erstellen der Back-Ends
Um ein Back-End in Azure API Management zu erstellen, müssen Sie eine Back-End-Entität definieren. So definieren Sie ein Back-End in Bicep:
resource backend2 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
parent: apimService
name: 'backend2'
properties: {
url: '${openai2Endpoint}openai'
protocol: 'http'
circuitBreaker: {
rules: [
{
failureCondition: {
count: 3
errorReasons: [
'Server errors'
]
interval: 'P1D'
statusCodeRanges: [
{
min: 500
max: 599
}
]
}
name: 'myBreakerRule'
tripDuration: 'PT1H'
}
]
}
}
Im vorherigen Bicep-Code wird ein Back-End definiert, das einer API-Endpunkt-URL entspricht. Beachten Sie auch den Namen backend2
. Diesen Namen benötigen wir später. Jedes vorhandene Back-End sollte wie der vorherige Bicep-Code codiert werden.
Hinweis
Denken Sie daran, dass Sie über mehrere Back-Ends verfügen können. Definieren Sie also so viele Back-Ends wie nötig.
Erstellen eines Back-End-Pools
Als Nächstes erstellen wir einen Back-End-Pool, der festlegt, auf welche Back-Ends wir die Last verteilen möchten. Wir können diesen Back-End-Pool wie folgt als Back-End-Entität codieren:
resource loadBalancing 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
parent: apimService
name: 'LoadBalancer'
properties: {
description: 'Load balancer for multiple backends'
type: 'Pool'
pool: {
services: [
{
id: '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${apimService.name}/backends/${backend1.id}'
}
{
id: '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ApiManagement/service/${apimService.name}/backends/${backend2.id}'
}
]
}
}
}
Das Back-End, das wir zuvor erstellt haben, backend2
, wird zusammen mit einem anderen Back-End, backend1
, referenziert, wobei letzteres aus Platzgründen weggelassen wurde.
Wir können auch eine priority
- und weight
-Eigenschaft für jedes Element in der Liste services
einschließen, um zu bestimmen, wie das Lastenausgleichsmodul die Last verteilt. Im Folgenden erfahren Sie, wie Sie die Priorität und Gewichtung für jedes Back-End festlegen können:
services: [
{
id: '/subscriptions/<subscriptionID>/resourceGroups/<resourceGroupName>/providers/Microsoft.ApiManagement/service/<APIManagementName>/backends/backend-1'
priority: 1
weight: 3
}
{
id: '/subscriptions/<subscriptionID>/resourceGroups/<resourceGroupName>/providers/Microsoft.ApiManagement/service/<APIManagementName>/backends/backend-2'
priority: 1
weight: 1
}
]
Im vorherigen Beispiel verteilt der Lastenausgleich die Last auf backend-1
dreimal mehr als backend-2
.
Weiterleiten eingehender Aufrufe
Schließlich müssen wir alle eingehenden Aufrufe an dieses Lastenausgleichs-Back-End weiterleiten. Die Weiterleitungsanweisung wird mit der folgenden API-Entität erstellt:
resource api1 'Microsoft.ApiManagement/service/apis@2020-06-01-preview' = {
parent: apimService
name: apiName
properties: {
displayName: apiName
apiType: 'http'
path: apiSuffix
format: 'openapi+json-link'
value: 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/preview/2024-03-01-preview/inference.json'
subscriptionKeyParameterNames: {
header: 'api-key'
}
}
Konfigurieren der Richtlinie
Jetzt können wir die Richtlinie für die zuvor beschriebene API festlegen und die eingehenden Aufrufe an den Lastenausgleich weiterleiten:
// policy.xml
<policies>
<inbound>
<base />
<set-backend-service id="apim-generated-policy" backend-id="{0}" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
var headerPolicyXml = format(loadTextContent('./policy.xml'), loadBalancing.name, 5000)
// Create a policy for the API, using the headerPolicyXml variable
resource apiPolicy 'Microsoft.ApiManagement/service/apis/policies@2020-06-01-preview' = {
parent: api1
name: 'policy'
properties: {
format: 'rawxml'
value: headerPolicyXml
}
}
Wir haben eine Richtlinie erstellt, die die eingehenden Anrufe an das Lastenausgleichsmodul leitet. Die set-backend-service
-Richtlinie wird verwendet, um die eingehenden Anrufe an das Lastenausgleichsmodul zu leiten. Die backend-id
-Eigenschaft wird auf den Namen des zuvor erstellten Lastenausgleichs festgelegt.
Mit all diesen beweglichen Teilen ist Ihre API Management-Instanz jetzt ausgeglichen. Sie können Ihre API jetzt skalieren, indem Sie dem Lastenausgleich weitere Back-Ends hinzufügen.
Trennschalter
Ein Trennschalter schützt Ihre API vor der Überlastung durch Anforderungen. Das funktioniert so: Sie definieren eine Reihe von Regeln, bei deren Erfüllung der Trennschalter auslöst und keine Anfragen mehr an das Back-End sendet. In Azure API Management können Sie einen Trennschalter definieren, indem Sie ein Back-End einrichten und eine Trennschalterregel definieren. Gehen Sie hierzu wie folgt vor:
resource backend2 'Microsoft.ApiManagement/service/backends@2023-09-01-preview' = {
parent: apimService
name: 'backend2'
properties: {
url: '${openai2Endpoint}openai'
protocol: 'http'
circuitBreaker: {
rules: [
{
failureCondition: {
count: 3
errorReasons: [
'Server errors'
]
interval: 'P1D'
statusCodeRanges: [
{
min: 500
max: 599
}
]
}
name: 'myBreakerRule'
tripDuration: 'PT1H'
}
]
}
}
}
In der vorherigen Back-End-Definition gibt es eine Eigenschaft failureCondition
, die definiert, wann der Trennschalter auslöst. In diesem Fall wird der Trennschalter ausgelöst, wenn an einem Tag drei Serverfehler auftreten. Die tripDuration
-Eigenschaft definiert, wie lange der Trennschalter geöffnet bleiben soll, bevor er wieder geschlossen wird. Es empfiehlt sich, einen Trennschalter für jedes Back-End in Ihrer API Management-Instanz zu definieren.
Verwaltete Identität
Ein weiteres Problem, das wir angehen sollten, ist die Sicherheit. Sie sollten sicherstellen, dass Ihre API sicher ist und nur autorisierte Clients darauf zugreifen können. Eine Möglichkeit, Ihre API zu sichern, ist eine verwaltete Identität. Verwaltete Identität ist eine Möglichkeit, Ihre API bei anderen Azure-Diensten zu authentifizieren. In Azure API Management müssen Sie verwaltete Identitäten an mehreren Stellen anwenden:
APIM-Instanzebene: Sie können verwaltete Identität in der APIM-Instanz aktivieren, indem Sie die
identity
-Eigenschaft aufSystemAssigned
festlegen:resource apimService 'Microsoft.ApiManagement/service@2023-09-01-preview' = { name: name location: location tags: union(tags, { 'azd-service-name': name }) sku: { name: sku capacity: (sku == 'Consumption') ? 0 : ((sku == 'Developer') ? 1 : skuCount) } properties: { publisherEmail: publisherEmail publisherName: publisherName // Custom properties are not supported for Consumption SKU } identity: { type: 'SystemAssigned' } }
Diese Aktion generiert eine verwaltete Identität für die APIM-Instanz, die wir später für unsere APIM-Instanz verwenden können, z. B. eine Azure OpenAI-Instanz.
API-Ebene: Sie können Ihrer API-Instanz eine Richtlinie zuordnen. In dieser Richtlinie können Sie die erforderlichen Anweisungen hinzufügen, damit die verwaltete Identität funktioniert:
<policies> <inbound> <base /> <authentication-managed-identity resource="https://cognitiveservices.azure.com" output-token-variable-name="managed-id-access-token" ignore-error="false" /> <set-header name="Authorization" exists-action="override"> <value>@("Bearer " + (string)context.Variables["managed-id-access-token"])</value> </set-header> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>
Sehen Sie sich die vorherigen Aufrufe von
authentication-managed-identity
undset-header
an. Diese Anweisungen stellen sicher, dass die verwaltete Identität auf die API angewendet wird.Back-End-Ebene: Sorgen Sie schließlich dafür, dass Ihre Back-Ends auf Azure OpenAI-Instanzen verweisen. Wir müssen unsere APIM-Instanz mit den Azure OpenAI-Instanzen verbinden. Mit dieser Bicep-Anweisung wird die Verbindung hergestellt:
resource role 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid(subscription().id, resourceGroup().id, principalId, roleDefinitionId) properties: { principalId: principalId principalType: "ServicePrincipal" roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId) } }
Zweck der obigen Bicep-Anweisung ist es, eine Rollenzuweisung zwischen der APIM-Instanz und der Azure-OpenAI-Instanz zu erstellen. In diesem Fall:
principalId
ist die Identitäts-ID aus der APIM-Instanz.roleDefinitionId
ist der spezifische Benutzer, in diesem Fall ein Benutzer namens „Cognitive Services User“, der Zugriff auf die Azure OpenAI-Instanz hat.name
: Diese Eigenschaft stellt sicher, dass die Rollenzuweisung auf den richtigen Bereich angewendet wird, was in diesem Fall eine bestimmte Abonnement- und Ressourcengruppe ist. (muss dieselbe Ressourcengruppe wie die Azure OpenAI-Instanz sein)