API-beheer

Voltooid

Wat is het probleem dat ik ondervind, waardoor ik een API Management-oplossing wil zoeken? Waarschijnlijk hebt u de volgende uitdagingen:

  • Schalen, uw API of API's worden door veel clients in verschillende regio's ter wereld gebruikt en u moet ervoor zorgen dat deze beschikbaar en responsief is.
  • Beveiliging, u moet ervoor zorgen dat uw API veilig is en dat alleen geautoriseerde clients er toegang toe hebben.
  • Foutbeheer, moet u ervoor zorgen dat uw API fouten probleemloos kan verwerken.
  • U moet uw API's bewaken om ervoor te zorgen dat deze naar verwachting worden uitgevoerd.
  • Tolerantie, u moet ervoor zorgen dat uw API tolerant is en fouten probleemloos kan afhandelen.

Voor elk van deze uitdagingen kunt u kiezen voor een puntoplossing, maar dat kan lastig zijn om te beheren. Houd er ook rekening mee dat uw API's kunnen worden gebouwd in verschillende technische stacks, wat betekent dat de oplossingen voor bovenstaande uitdagingen kunnen betekenen dat u verschillende oplossingen nodig hebt voor elke API. Als u al deze uitdagingen ondervindt, moet u een gecentraliseerde API Management-oplossing overwegen, zoals Azure API Management.

Laten we dieper ingaan op enkele uitdagingen en kijken hoe een gecentraliseerde API Management-oplossing, zoals Azure API Management, u kan helpen deze problemen op te lossen.

Infrastructuur als code, IaC

Het is prima om uw Azure-resources te maken met behulp van Azure Portal, maar naarmate uw infrastructuur groeit, wordt het moeilijker om te beheren. Een van de problemen die u ondervindt, is dat u uw infrastructuur niet eenvoudig in een andere omgeving kunt repliceren.

Het is ook moeilijk om alle wijzigingen te traceren die zijn aangebracht in uw infrastructuur. Deze situatie is waar Infrastructure as Code (IaC) binnenkomt. IaC is de praktijk van het beheren van uw infrastructuur met behulp van code. Als u IaC op Azure wilt toepassen, hebt u verschillende opties, een daarvan is Bicep. Bicep is een DOMAIN Specific Language (DSL) voor het implementeren van Azure-resources declaratief. Het is een uitstekende manier om uw cloudresources te beheren. Hier volgt een eenvoudig voorbeeld van hoe Bicep eruitziet:

param location string = 'eastus'

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
  name: 'mystorageaccount'
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

In het voorgaande voorbeeld hebben we een opslagaccount gedefinieerd met Bicep. We hebben de locatie gedefinieerd van het opslagaccount, het soort opslagaccount en de SKU (voorraadbeheereenheid). Locatie is een parameter die we kunnen doorgeven wanneer we het Bicep-bestand implementeren. Om het gepresenteerde bestand te implementeren, gebruiken we de Azure CLI als volgt:

az deployment group create --resource-group myResourceGroup --template-file main.bicep

Met de voorgaande opdracht wordt het opslagaccount geïmplementeerd in de resourcegroep myResourceGroup en wordt het Bicep-bestand main.bicep gebruikt om de resources in het bestand te maken.

Belasting verwerken via een load balancer

Het toevoegen van een taakverdelingsconstructie is het antwoord wanneer het probleem is dat uw API wordt overweldigd door aanvragen. Met een load balancer kunt u de belasting verdelen over meerdere exemplaren van uw API.

In de Azure API Management-service wordt taakverdeling geïmplementeerd door u een concept met de naam back-ends te definiëren. Het idee is dat u veel back-ends instelt die overeenkomen met uw API-eindpunten en vervolgens een load balancer maakt die de belasting over deze back-ends distribueert. De architectuur ziet er als volgt uit:

Schermopname van een load balancer.

Wat er gebeurt in de voorgaande architectuur is:

  1. De client verzendt een aanvraag naar het API Management-exemplaar.
  2. De aanvraag wordt geverifieerd en geautoriseerd.
  3. De aanvraag wordt vervolgens verzonden naar de load balancer.
  4. De load balancer distribueert de aanvraag naar een van de back-ends (geselecteerde Azure OpenAI-API wordt vetgedrukt aangegeven).

De back-end verwerkt de aanvraag en stuurt een antwoord terug naar de client.

De load balancer definiëren

Als u een load balancer wilt instellen in Azure API Management, moet u de volgende onderdelen uitvoeren:

  • Back-ends, zoveel back-ends als u de belasting wilt distribueren.
  • Load balancer, een load balancer die de back-ends bevat waar u de belasting over wilt verdelen.
  • Een beleid waarmee de binnenkomende aanroepen naar de load balancer worden omgeslagen.

De back-ends maken

Als u een back-end wilt maken in Azure API Management, moet u een back-endentiteit definiëren. U kunt als volgt een back-end definiëren 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'
        }
      ]
    }
}

In de voorgaande Bicep-code wordt een back-end gedefinieerd die overeenkomt met een API-eindpunt-URL. U ziet ook dat de naam backend2 deze naam later kan worden gebruikt. Voor elke back-end die u hebt, moet u deze coderen zoals de voorgaande bicep-code.

Notitie

Houd er rekening mee dat u meerdere back-ends kunt hebben, zodat u zoveel back-ends kunt definiëren als u wilt.

Back-endpool maken

Vervolgens willen we een back-endpool maken waarmee wordt ingesteld tussen welke back-ends we de belasting willen verdelen. We kunnen deze back-endpool als een back-endentiteit als volgt coderen:

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}'
        }
      ]
    }
  }
}

De back-end die we eerder hebben gemaakt, backend2wordt samen met een andere back-end backend1verwezen, de laatste die we hebben weggelaten voor beknoptheid.

We kunnen ook een priority en weight eigenschap opnemen voor elk item in de services lijst om te bepalen hoe de load balancer de belasting distribueert. U kunt als volgt de prioriteit en het gewicht voor elke back-end instellen:

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
    }
  ]

In het vorige voorbeeld verdeelt de load balancer de belasting naar backend-1 drie keer meer dan backend-2.

Directe binnenkomende oproepen

Ten slotte moeten we binnenkomende aanroepen naar deze back-end voor taakverdeling doorsturen. De instructie voor de richting wordt gemaakt met de volgende API-entiteit:

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'
    }
    
}

Het beleid configureren

Ten slotte kunnen we het beleid voor eerder beschreven API instellen en de binnenkomende aanroepen naar de load balancer doorsturen:

// 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
  }
}

We hebben een beleid gemaakt waarmee de binnenkomende aanroepen naar de load balancer worden omgeslagen. Het set-backend-service beleid wordt gebruikt om de binnenkomende aanroepen naar de load balancer te leiden. De backend-id eigenschap is ingesteld op de naam van de load balancer die we eerder hebben gemaakt.

Nu al deze bewegende onderdelen aanwezig zijn, is uw API Management-exemplaar nu taakverdeling. U kunt uw API nu schalen door meer back-ends toe te voegen aan de load balancer.

Stroomonderbreker

Een circuitonderbreker is iets dat u gebruikt wanneer u uw API wilt beschermen tegen overweldiging door aanvragen. Hoe het werkt, is dat u een set regels definieert die wanneer aan de regel wordt voldaan, de circuitonderbreker activeert en stopt met het verzenden van aanvragen naar de back-end. In Azure API Management kunt u een circuitonderbreker definiëren door een back-end in te stellen en een circuitonderbrekerregel te definiëren. U kunt dit als volgt doen:

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 de voorgaande back-enddefinitie is er een eigenschap failureCondition die definieert wanneer de circuitonderbreker moet reizen. In dit geval wordt de circuitonderbreker gereisd als er drie serverfouten per dag zijn. De tripDuration eigenschap bepaalt hoe lang de circuitonderbreker open moet blijven voordat deze opnieuw wordt gesloten. Het is raadzaam om een circuitonderbreker te definiëren voor elke back-end die u in uw API Management-exemplaar hebt.

Beheerde identiteit

Een ander probleem dat we willen aanpakken, is beveiliging. U wilt ervoor zorgen dat uw API veilig is en dat alleen geautoriseerde clients er toegang toe hebben. Een manier om uw API te beveiligen, is door beheerde identiteit te gebruiken. Beheerde identiteit is een manier om uw API te verifiëren bij andere Azure-services. In Azure API Management moet u beheerde identiteit op verschillende plaatsen toepassen, namelijk:

  • Op APIM-exemplaarniveau kunt u beheerde identiteit inschakelen in het APIM-exemplaar door de identity eigenschap als volgt in te SystemAssigned stellen:

    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'
        }
    }
    

    Met deze actie wordt een beheerde identiteit gegenereerd voor het APIM-exemplaar dat we later kunnen gebruiken voor bijvoorbeeld een Azure OpenAI-exemplaar.

  • API-niveau voor uw API-exemplaar kunt u het koppelen aan een beleid. In dit beleid kunt u de benodigde instructies toevoegen om de beheerde identiteit te laten werken:

    <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>
    

    Bekijk de voorgaande aanroepen naar authentication-managed-identity en set-header deze instructies zorgen ervoor dat de beheerde identiteit wordt toegepast op de API.

  • Ten slotte wijst het back-endniveau op uw back-ends naar Azure OpenAI-exemplaren. We moeten ons APIM-exemplaar verbinden met de Azure OpenAI-instantie/s. Hier volgt de Bicep-instructie om deze verbinding te maken:

    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)
      }
    }
    

    Het idee met bovenstaande Bicep-instructie is het maken van een roltoewijzing tussen het APIM-exemplaar en het Azure OpenAI-exemplaar. In dit geval:

    • principalId is de id van het APIM-exemplaar,
    • roleDefinitionId is de specifieke gebruiker, in dit geval een gebruiker met de naam Cognitive Services-gebruiker, een gebruiker die toegang heeft tot het Azure OpenAI-exemplaar.
    • name, deze eigenschap zorgt ervoor dat de roltoewijzing wordt toegepast op het juiste bereik, wat in dit geval een specifiek abonnement en een specifieke resourcegroep is. (moet dezelfde resourcegroep zijn als het Azure OpenAI-exemplaar)

Kennis testen

1.

Wat is een van de belangrijkste uitdagingen waarmee u een API Management-oplossing kunt zoeken?

2.

Waarvoor wordt Infrastructure as Code (IaC) gebruikt bij het beheren van Azure-resources?

3.

Wat is het doel van een circuitonderbreker in API Management?