VENDITE: 1-800-867-1389

Gestione di errori di comunicazione temporanei

Aggiornamento: settembre 2014

Per migliorare l'affidabilità di una soluzione che utilizza l'API di messaggistica negoziata gestita .NET Service Bus di Microsoft Azure, è consigliabile adottare un approccio coerente per la gestione degli errori temporanei e intermittenti che possono verificarsi quando la soluzione comunica con l'infrastruttura del servizio di messaggistica di pubblicazione/sottoscrizione e accodamento basata su cloud e multi-tenant fornita da Service Bus.

Per migliorare l'affidabilità di una soluzione che utilizza l'API di messaggistica negoziata gestita .NET Service Bus, è consigliabile adottare un approccio coerente per la gestione degli errori temporanei e intermittenti che possono verificarsi quando la soluzione comunica con l'infrastruttura del servizio di messaggistica di pubblicazione/sottoscrizione e accodamento basata su cloud e multi-tenant fornita da Service Bus.

Nel considerare una tecnica specifica per il rilevamento delle condizioni temporanee, può essere utile riutilizzare le soluzioni tecniche esistenti, ad esempio il framework di gestione di errori temporanei, oppure compilarne di personalizzate. In entrambi i casi, è necessario verificare che solo un subset di eccezioni di comunicazione sia considerato temporaneo prima di tentare il recupero dai rispettivi errori.

Nella tabella riportata di seguito viene fornito un elenco di eccezioni che è possibile compensare con l'implementazione della logica di ripetizione tentativi:

 

Tipo di eccezione

Indicazione

ServerBusyException

Questa eccezione può essere causata da un errore intermittente nell'infrastruttura del servizio di messaggistica di Service Bus che non è in grado di elaborare una richiesta a causa di condizioni locali anomale temporizzate. Il client può ripetere il tentativo con un ritardo. Un ritardo di back-off sarebbe preferibile per evitare un'ulteriore pressione non necessaria sul server.

MessagingCommunicationException

Questa eccezione segnala un errore di comunicazione che può verificarsi quando non è possibile stabilire una connessione tra il client di messaggistica e l'infrastruttura di Service Bus. Nella maggior parte dei casi, se è presente la connettività di rete, questo errore può essere considerato temporaneo. Il client può tentare di ripetere l'operazione che ha restituito questo tipo di eccezione. È inoltre consigliabile verificare se il servizio di risoluzione dei nomi di dominio (DNS) è operativo in quanto questo errore potrebbe indicare che non è possibile risolvere il nome host di destinazione.

TimeoutException

Questa eccezione indica che l'infrastruttura del servizio di messaggistica di Service Bus non ha risposto all'operazione richiesta nel tempo specificato, determinato dall'impostazione OperationTimeout. L'operazione richiesta potrebbe essere stata completata, tuttavia a causa di ritardi della rete o di altre infrastrutture, la risposta potrebbe non avere raggiunto il client in modo tempestivo. La compensazione di questo tipo di eccezioni deve essere effettuata con cautela. Se un messaggio è stato recapitato a una coda, ma si è verificato un timeout della risposta, il rinvio del messaggio originale causa una duplicazione.

Per ulteriori informazioni dettagliate sui diversi tipi di eccezioni che possono essere segnalate dall'API di messaggistica di Service Bus, vedere l'argomento Eccezioni di messaggistica.

noteNota
Nella gestione di errori di comunicazione temporanei, prestare attenzione alle eccezioni temporanee mascherate da eccezioni esterne di tipo diverso. Ad esempio, un timeout potrebbe essere restituito al chiamante sotto forma di errore di comunicazione che nasconde il timeout originale come eccezione interna. È pertanto consigliabile esaminare tutte le eccezioni interne di un determinato oggetto di eccezione in modo ricorsivo per individuare con affidabilità gli errori di comunicazione temporanei. La classe ServiceBusTransientErrorDetectionStrategy nel framework di gestione di errori temporanei offre un esempio relativo a questa operazione.

Il frammento di codice seguente illustra come inviare un messaggio in modo asincrono a un argomento Service Bus verificando che tutti gli errori temporanei noti siano compensati da un nuovo tentativo. Si noti che questo esempio di codice mantiene una dipendenza dal framework di gestione di errori temporanei.

var credentials = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);
var address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, String.Empty);
var messagingFactory = MessagingFactory.Create(address, credentials);
var topicClient = messagingFactory.CreateTopicClient(topicPath);
var retryPolicy = new RetryPolicy<ServiceBusTransientErrorDetectionStrategy>(RetryPolicy.DefaultClientRetryCount);

// Create an instance of the object that represents message payload.
var payload = XDocument.Load("InventoryFile.xml");

// Declare a BrokeredMessage instance outside so that it can be reused across all 3 delegates below.
BrokeredMessage msg = null;

// Use a retry policy to execute the Send action in an asynchronous and reliable fashion.
retryPolicy.ExecuteAction
(
    (cb) =>
    {
        // A new BrokeredMessage instance must be created each time we send it. Reusing the original BrokeredMessage instance may not 
        // work as the state of its BodyStream cannot be guaranteed to be readable from the beginning.
        msg = new BrokeredMessage(payload.Root, new DataContractSerializer(typeof(XElement)));

        // Send the event asynchronously.
        topicClient.BeginSend(msg, cb, null);
    },
    (ar) =>
    {
        try
        {
            // Complete the asynchronous operation. 
            // This may throw an exception that will be handled internally by the retry policy.
            topicClient.EndSend(ar);
        }
        finally
        {
            // Ensure that any resources allocated by a BrokeredMessage instance are released.
            if (msg != null)
            {
                msg.Dispose();
                msg = null;
            }
        }
    },
    (ex) =>
    {
        // Always dispose the BrokeredMessage instance even if the send 
        // operation has completed unsuccessfully.
        if (msg != null)
        {
            msg.Dispose();
            msg = null;
        }

        // Always log exceptions.
        Trace.TraceError(ex.Message);
    }
);

Nel successivo esempio di codice viene illustrato come creare in modo affidabile un nuovo argomento di Service Bus o recuperarne uno esistente. Anche questo codice mantiene una dipendenza dal framework di gestione di errori temporanei che tenterà automaticamente di ripetere l'operazione di gestione corrispondente se non può essere completata correttamente a causa di errori di connettività intermittenti o altri tipi di condizioni temporanee:

public TopicDescription GetOrCreateTopic(string issuerName, string issuerSecret, string serviceNamespace, string topicName)
{
    // Must validate all input parameters here. Use Code Contracts or build your own validation.
    var credentials = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);
    var address = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, String.Empty);
    var nsManager = new NamespaceManager(address, credentials);
    var retryPolicy = new RetryPolicy<ServiceBusTransientErrorDetectionStrategy>(RetryPolicy.DefaultClientRetryCount);

    TopicDescription topic = null;
    bool createNew = false;

    try
    {
        // First, let's see if a topic with the specified name already exists.
        topic = retryPolicy.ExecuteAction<TopicDescription>(() => { return nsManager.GetTopic(topicName); });

        createNew = (topic == null);
    }
    catch (MessagingEntityNotFoundException)
    {
        // Looks like the topic does not exist. We should create a new one.
        createNew = true;
    }

    // If a topic with the specified name doesn't exist, it will be auto-created.
    if (createNew)
    {
        try
        {
            var newTopic = new TopicDescription(topicName);

            topic = retryPolicy.ExecuteAction<TopicDescription>(() => { return nsManager.CreateTopic(newTopic); });
        }
        catch (MessagingEntityAlreadyExistsException)
        {
            // A topic under the same name was already created by someone else, 
            // perhaps by another instance. Let's just use it.
            topic = retryPolicy.ExecuteAction<TopicDescription>(() => { return nsManager.GetTopic(topicName); });
        }
    }

    return topic;
}

In breve, si consiglia di valutare la probabilità che si verifichi un errore e determinare la possibilità di aggiungere ulteriore resilienza. Virtualmente, tutte le operazioni di messaggistica possono essere soggette a condizioni temporanee. Quando si chiama l'API di messaggistica negoziata, pertanto, è consigliabile adottare le misure appropriate per fornire sempre il recupero da errori intermittenti.

Il documento è risultato utile?
(1500 caratteri rimanenti)
Grazie per i commenti inviati.
Mostra:
© 2014 Microsoft