Pipeline HTTP e criteri di ripetizione nell'SDK di Azure per C++

Azure SDK per C++ usa un'architettura della pipeline HTTP per elaborare le richieste HTTP ai servizi di Azure. Questo documento illustra il funzionamento delle pipeline HTTP, il modo in cui vengono implementati i criteri di ripetizione dei tentativi e come personalizzarli in base alle esigenze dell'applicazione.

Architettura della pipeline HTTP

Che cos'è una pipeline HTTP?

Una pipeline HTTP è uno stack di criteri HTTP applicati in sequenza per elaborare richieste e risposte HTTP. Ogni client in Azure SDK ha una propria pipeline HTTP. I criteri nella pipeline modellano il modo in cui vengono gestite le richieste HTTP, incluse le operazioni come:

  • Aggiunta di intestazioni di autenticazione
  • Registrazione richiesta-risposta
  • Logica di ripetizione dei tentativi per le richieste non riuscite
  • Raccolta di dati di telemetria
  • Gestione del trasporto (invio effettivo della richiesta HTTP)

La pipeline è suddivisa in due parti principali:

  • Criteri per chiamata: eseguire una sola volta per ogni operazione API.
  • Criteri per ogni tentativo: eseguire per ogni nuovo tentativo.

Questa struttura garantisce che i criteri appropriati (ad esempio l'autenticazione) vengono eseguiti una sola volta per ogni operazione, mentre altri (ad esempio la registrazione) vengono eseguiti per ogni tentativo di ripetizione.

Ordinamento delle politiche

Una tipica pipeline HTTP in Azure SDK per C++ include i criteri seguenti nell'ordine:

  1. Criterio di telemetria (per chiamata): aggiunge informazioni di telemetria dell'SDK di Azure.
  2. Criterio per l'ID della richiesta (per chiamata): garantisce che ogni richiesta abbia un ID univoco.
  3. Criteri per chiamata specifici del servizio: criteri personalizzati specifici del servizio.
  4. Criterio di ripetizione (per chiamata): Implementa la logica di ripetizione.
  5. Criteri specifici del servizio per ogni tentativo: criteri personalizzati specifici del servizio applicati a ogni tentativo.
  6. Criterio di attività della richiesta (per ogni tentativo): gestisce il tracciamento distribuito.
  7. Criterio di registrazione (per tentativo): gestisce la registrazione delle richieste e delle risposte.
  8. Criteri di trasporto (per tentativo): gestisce l'invio effettivo della richiesta HTTP.

Diagramma che mostra le fasi dei criteri della pipeline HTTP di Azure SDK per C++.

Criteri di ripetizione

Meccanismo dei tentativi

I criteri di ripetizione dei tentativi sono progettati per gestire gli errori temporanei che possono verificarsi durante l'esecuzione di richieste HTTP ai servizi di Azure. Quando una richiesta non riesce a causa di un errore temporaneo, il criterio di ripetizione esegue le operazioni seguenti:

  1. Determina se l'errore è riprovabile.
  2. Calcola un ritardo adeguato.
  3. Attende il ritardo.
  4. Ritenta la richiesta.

I criteri supportano la ripetizione dei tentativi in caso di errori a livello di trasporto (problemi di rete) e di determinati codici di stato HTTP.

Comportamento di ripetizione dei tentativi predefinito

Per impostazione predefinita, i criteri di ripetizione dei tentativi sono configurati con:

  • Massimo tre tentativi
  • Ritardo iniziale dei tentativi di 800 millisecondi
  • Ritardo massimo di ripetizione di 60 secondi
  • Codici di stato riprovabili: 408, 429, 500, 502, 503, 504

Il ritardo del tentativo di ripetizione usa una strategia di backoff esponenziale con jitter.

  • Primo tentativo: ~800 ms
  • Secondo tentativo: ~1.600 ms
  • Terzo tentativo: ~3.200 ms
  • Il ritardo raddoppia continuamente fino a raggiungere il ritardo massimo tra i tentativi.

Quando si verificano nuovi tentativi

La politica di ripetizione tenta di ripetere una richiesta nei seguenti scenari:

  • Errori di trasporto:

    • Problemi relativi alla connettività di rete
    • Timeout delle connessioni
    • Errori di risoluzione DNS (Domain Name System)
  • Codici di stato HTTP:

    • 408 (Timeout della richiesta)
    • 429 (Troppe richieste)
    • 500 (Errore interno del server)
    • 502 (Gateway non valido)
    • 503 (Servizio non disponibile)
    • 504 (timeout del gateway)
  • Logica di ripetizione dei tentativi specifica del servizio:

    • Alcuni servizi come Archiviazione implementano la logica di ripetizione dei tentativi specializzata per gli scenari di failover

Personalizzazione del comportamento di ripetizione dei tentativi

È possibile personalizzare il comportamento di ripetizione dei tentativi durante la creazione di un client modificando il RetryOptions nelle opzioni del client.

Esempio: personalizzazione delle opzioni di ripetizione dei tentativi

#include <azure/storage/blobs.hpp>

int main() 
{
    // Create client options
    Azure::Storage::Blobs::BlobClientOptions options;
    
    // Modify retry options
    options.Retry.MaxRetries = 5;                                    // Increase max retries
    options.Retry.RetryDelay = std::chrono::milliseconds(1000);      // Set initial retry delay to 1 second
    options.Retry.MaxRetryDelay = std::chrono::seconds(30);          // Cap maximum retry delay at 30 seconds
    
    // Add a custom status code to retry on
    options.Retry.StatusCodes.insert(Azure::Core::Http::HttpStatusCode::Forbidden); // Retry on 403 errors
    
    // Create the client with custom retry options
    auto blobClient = Azure::Storage::Blobs::BlobClient::CreateFromConnectionString(
        connectionString,
        containerName,
        blobName,
        options);
    
    // Use the client...
}

Aggiunta di criteri personalizzati

È possibile aggiungere criteri personalizzati alla pipeline HTTP per implementare un comportamento specializzato:

Aggiungere un criterio per operazione

Le politiche per operazione singola sono applicate una volta per operazione API, indipendentemente dal numero di tentativi richiesti.

class MyCustomPolicy final : public Azure::Core::Http::Policies::HttpPolicy {
public:
    ~MyCustomPolicy() override = default;
    std::unique_ptr<HttpPolicy> Clone() const override
    {
        return std::make_unique<MyCustomPolicy>(*this);
    }

    std::unique_ptr<Azure::Core::Http::RawResponse> Send(
        Azure::Core::Http::Request& request,
        Azure::Core::Http::Policies::NextHttpPolicy nextPolicy,
        Azure::Core::Context const& context) const override
    {
        // Custom logic before the request
        
        auto response = nextPolicy.Send(request, context);
        
        // Custom logic after the response
        
        return response;
    }
};

// Adding the policy to client options
Azure::Storage::Blobs::BlobClientOptions options;
options.PerOperationPolicies.emplace_back(std::make_unique<MyCustomPolicy>());

Aggiunta di una politica per ritentativi

Le politiche di riprovazione vengono applicate a ogni nuovo tentativo.

// Similar implementation to above, but add to PerRetryPolicies
options.PerRetryPolicies.emplace_back(std::make_unique<MyCustomRetryPolicy>());

Gestione degli endpoint secondari

Alcuni servizi di Azure, ad esempio Archiviazione, supportano endpoint secondari per la disponibilità elevata. L'SDK include il supporto per il failover automatico agli endpoint secondari:

Azure::Storage::Blobs::BlobClientOptions options;

// Configure secondary endpoint for Storage
std::string primaryUrl = blobClient.GetUrl();
std::string secondaryUrl = InferSecondaryUrl(primaryUrl); // Your logic to determine secondary URL
std::string secondaryHost = Azure::Core::Url(secondaryUrl).GetHost();

options.SecondaryHostForRetryReads = secondaryHost;

Registrazione dei tentativi di ripetizione

La pipeline HTTP include la registrazione predefinita per i tentativi di ripetizione. È possibile configurare il livello di registrazione per visualizzare informazioni sui tentativi:

// Set log level to see retry information
Azure::Core::Diagnostics::Logger::SetLevel(Azure::Core::Diagnostics::Logger::Level::Informational);

// Set a custom log listener to capture logs
Azure::Core::Diagnostics::Logger::SetListener([](auto level, auto message) {
    std::cout << "Log [" << static_cast<int>(level) << "]: " << message << std::endl;
});

Quando si verifica un nuovo tentativo, le voci di log vengono visualizzate come segue:

  • "Errore di trasporto HTTP: [dettagli errore]"
  • Tentativo di ritentare HTTP #1 sarà effettuato in 800 ms.
  • Il codice di stato HTTP 503 verrà tentato di nuovo.

Procedure consigliate

  • Usare le impostazioni predefinite per i tentativi quando possibile. Le impostazioni predefinite funzionano bene per la maggior parte degli scenari e includono procedure consigliate come backoff esponenziale.
  • Fare attenzione alle operazioni non idempotenti. Valutare la possibilità di limitare i nuovi tentativi per le operazioni che non possono essere ritentate in sicurezza, ad esempio le richieste POST non idempotenti.
  • Prendere in considerazione i modelli di interruttore. Per le applicazioni con volumi elevati, implementare modelli di interruttore per evitare un sovraccarico dei servizi che rispondono con errori.
  • Scenari di ripetizione dei test. Testare il comportamento dell'applicazione quando si verificano nuovi tentativi per garantire una corretta gestione.
  • Monitora la telemetria dei tentativi. Tassi di ripetizione elevati possono indicare problemi sottostanti che devono essere risolti.

Avanzato: meccanismi interni della pipeline

La pipeline HTTP viene implementata nella Azure::Core::Http::_internal::HttpPipeline classe , che gestisce la sequenza di esecuzione dei criteri. Quando viene effettuata una richiesta, la pipeline:

  1. Inizia con il primo criterio nella pipeline.
  2. Ogni criterio elabora la richiesta e quindi la passa al criterio successivo.
  3. L'ultimo criterio è in genere il criterio di trasporto, che invia la richiesta.
  4. La risposta ripercorre quindi le policy in ordine inverso.

Il criterio di ripetizione è speciale perché può ripetere l'intera sequenza di criteri che vengono dopo di esso nella pipeline.

Risoluzione dei problemi

Se si verificano problemi con i riavvii:

  • Abilitare la registrazione informativa. Impostare la variabile di ambiente AZURE_LOG_LEVEL su Informational per visualizzare i tentativi di ripetizione.
  • Verificare la presenza di errori di trasporto. I problemi di rete spesso si manifestano come eccezioni di trasporto.
  • Verifica lo stato del servizio. Gli errori persistenti a 500 livelli potrebbero indicare un problema del servizio Azure.
  • Rivedi gli ID delle richieste. Ogni richiesta ha un ID univoco che è possibile usare quando si usa il supporto Azure.
  • Controllare le impostazioni di timeout. Assicurati che i timeout della tua applicazione siano compatibili con la politica di ripetizione dei tentativi.