Questo argomento non è stato ancora valutato - Valuta questo argomento

Procedure consigliate per il miglioramento delle prestazioni tramite la messaggistica negoziata di Service Bus

In questo argomento viene descritto come utilizzare Windows Azure Service Bus per ottimizzare le prestazioni durante gli scambi di messaggi negoziati. Nella prima metà dell'argomento vengono illustrati i diversi meccanismi disponibili per migliorare le prestazioni. Nella seconda metà vengono fornite indicazioni per l'utilizzo di Service Bus in modo da garantire prestazioni ottimali per uno scenario specifico.

In questo argomento si utilizza il termine "client" per indicare qualsiasi entità che accede a Service Bus. Un client può assumere il ruolo di mittente o di ricevitore. Il termine "mittente" viene utilizzato per un client di coda o di argomento di Service Bus che invia messaggi a una coda o a un argomento di Service Bus. Il termine "ricevitore" viene utilizzato per indicare un client di coda o di sottoscrizione di Service Bus che riceve messaggi da una coda o da una sottoscrizione di Service Bus.

Meccanismi

In questa sezione vengono presentati i diversi concetti su cui si basa Service Bus per ottimizzare le prestazioni.

Protocolli

Service Bus consente ai client di inviare e ricevere messaggi attraverso due protocolli: il protocollo client di Service Bus e HTTP. Il protocollo client di Service Bus è più efficiente, poiché mantiene la connessione al servizio di Service Bus per tutta l'esistenza della factory di messaggistica. Implementa inoltre l'invio in batch e la prelettura. Il protocollo client di Service Bus è disponibile per le applicazioni .NET che utilizzano l'API gestita .NET.

A meno che non venga indicato diversamente, in tutto il contenuto di questo argomento si presuppone che venga utilizzato il protocollo client di Service Bus.

Riutilizzo di factory e client

Gli oggetti client di Service Bus, ad esempio QueueClient o MessageSender, vengono creati tramite un oggetto MessagingFactory, che fornisce anche la gestione interna delle connessioni. Dopo l'invio di un messaggio, è consigliabile non chiudere le factory di messaggistica o i client di coda, argomento e sottoscrizione per evitare di doverli ricreare quando si invia il messaggio successivo. Chiudendo una factory di messaggistica viene eliminata la connessione al servizio di Service Bus e quando si ricrea la factory viene stabilita una nuova connessione. Stabilire una connessione è un'operazione dispendiosa e può essere evitata riutilizzando gli stessi oggetti factory e client per più operazioni.

Operazioni simultanee

L'esecuzione di un'operazione (invio, ricezione, eliminazione e così via) richiede tempo. Il tempo richiesto comprende l'elaborazione dell'operazione da parte del servizio di Service Bus e la latenza della richiesta e della risposta. Per poter eseguire un numero maggiore di operazioni per volta, è necessario che le operazioni vengano eseguite simultaneamente. A tale scopo, è possibile procedere in diversi modi:

  • Operazioni asincrone: il client invia tramite pipeline le operazioni eseguendo operazioni asincrone. La richiesta successiva viene avviata prima del completamento della richiesta precedente. Viene riportato di seguito un esempio di un'operazione send asincrona:

    BrokeredMessage m1 = new BrokeredMessage(body);
    BrokeredMessage m2 = new BrokeredMessage(body);
    queueClient.BeginSend(m1, processEndSend, queueClient); // Send message 1.
    queueClient.BeginSend(m2, processEndSend, queueClient); // Send message 2.
    
    void processEndSend(IAsyncResult result)
    {
        QueueClient qc = result.AsyncState as QueueClient;
        qc.EndSend(result);
        Console.WriteLine("Message sent");
    }
    
    Viene riportato di seguito un esempio di un'operazione receive asincrona:

    queueClient.BeginReceive(processEndReceive, queueClient); // Receive message 1.
    queueClient.BeginReceive(processEndReceive, queueClient); // Receive message 2.
    
    void processEndReceive(IAsyncResult result) 
    {
        QueueClient qc = result.AsyncState as QueueClient;
        BrokeredMessage m = qc.EndReceive(result);
        m.BeginComplete(processEndComplete, m);
        Console.WriteLine("Received message " + m.Label);
    }
    
    void processEndComplete(IAsyncResult result)
    {
        BrokeredMessage m = result.AsyncState as BrokeredMessage;
        m.EndComplete(result);
        Console.WriteLine("Completed message " + m.Label);
    }
    
  • Factory multiple: tutti i client (mittenti oltre che ricevitori) creati dalla stessa factory condividono una connessione TCP. La velocità effettiva massima dei messaggi è limitata dal numero di operazioni che possono utilizzare questa connessione TCP. La velocità effettiva che è possibile ottenere con una singola factory varia in modo significativo in base alla dimensione dei messaggi e ai tempi di round trip TCP. Nei benchmark è stata osservata una velocità effettiva massima per factory di circa 800 msg/s (dimensione dei messaggi: 1 KB). Per ottenere velocità superiori, è consigliabile utilizzare più factory di messaggistica.

Modalità di ricezione

Quando si crea un client di coda o di sottoscrizione, è possibile specificare una modalità di ricezione: individuazione-blocco o ricezione ed eliminazione. La modalità di ricezione predefinita è PeekLock. Quando è attiva questa modalità, il client invia una richiesta per ricevere un messaggio da Service Bus. Dopo aver ricevuto il messaggio, il client invia una richiesta per completarlo.

Quando la modalità di ricezione è impostata su ReceiveAndDelete, entrambi i passaggi vengono combinati in una singola richiesta. In questo modo si riduce il numero complessivo di operazioni ed è possibile migliorare la velocità effettiva globale dei messaggi. A un aumento delle prestazioni corrisponde un maggior rischio di perdita dei messaggi.

La versione di Service Bus di settembre 2011 non supporta le transazioni per le operazioni di ricezione ed eliminazione. La semantica di individuazione-blocco inoltre è necessaria per tutti gli scenari in cui il client desidera posticipare un messaggio o impostare un messaggio come non recapitabile.

Invio in batch sul lato client

L'invio in batch sul lato client consente a un client di coda o di argomento di ritardare l'invio di un messaggio per un determinato intervallo di tempo. Se il client invia altri messaggi durante questo intervallo di tempo, li trasmette in un singolo batch. L'invio in batch sul lato client determina inoltre nel client di coda/sottoscrizione l'invio di più richieste Complete in una singola richiesta. L'invio in batch è disponibile solo per operazioni Send e Complete asincrone. Le operazioni sincrone invece vengono inviate immediatamente al servizio di Service Bus. L'invio in batch non viene eseguito tra client né per operazioni di visualizzazione o ricezione.

Se il batch supera la dimensione massima prevista per i messaggi, l'ultimo messaggio viene rimosso e il client invia immediatamente il batch. L'ultimo messaggio diventerà il primo del batch successivo. Per impostazione predefinita, un client utilizza un intervallo di batch di 20 ms. È possibile modificare l'intervallo di batch impostando la proprietà BatchFlushInterval prima della creazione della factory di messaggistica. Questa impostazione ha effetto su tutti i client creati dalla factory. Per disabilitare l'invio in batch, impostare la proprietà BatchFlushInterval su TimeSpan.Zero. come indicato nel seguente esempio:

MessagingFactorySettings mfs = new MessagingFactorySettings();
mfs.TokenProvider = tokenProvider;
mfs.NetMessagingTransportSettings.BatchFlushInterval = TimeSpan.FromSeconds(0.05);
MessagingFactory messagingFactory = MessagingFactory.Create(namespaceUri, mfs);

L'invio in batch non influisce sul numero di operazioni di messaggistica fatturabili ed è disponibile solo per il protocollo client di Service Bus. Il protocollo HTTP non supporta l'invio in batch.

Accesso in batch all'archivio

Per aumentare la velocità effettiva di una coda, un argomento o una sottoscrizione, il servizio di Service Bus inserisce più messaggi in batch quando scrive nell'archivio interno. Se si abilita questa funzionalità su una coda o un argomento, la scrittura di messaggi nell'archivio verrà effettuata in batch. Se si abilita questa funzionalità su una coda o una sottoscrizione, l'eliminazione di messaggi dall'archivio verrà effettuata in batch. Se per un'entità si abilita l'accesso in batch all'archivio, Service Bus ritarderà fino a 20 ms un'operazione di scrittura nell'archivio relativa a tale entità. Le eventuali operazioni di archivio aggiuntive eseguite in tale intervallo verranno aggiunte al batch. L'accesso in batch all'archivio ha effetto solo sulle operazioni Send e Complete, mentre le operazioni di ricezione non sono interessate. L'accesso in batch all'archivio è una proprietà per un'entità. L'invio in batch viene applicato a tutte le entità che consentono l'accesso in batch all'archivio.

Quando si crea una nuova coda, un nuovo argomento o una nuova sottoscrizione, l'accesso in batch all'archivio viene abilitato per impostazione predefinita. Per disabilitarlo, impostare la proprietà EnableBatchedOperations su false prima di creare l'entità. come indicato nel seguente esempio:

QueueDescription qd = new QueueDescription();
qd.EnableBatchedOperations = false;
Queue q = namespaceManager.CreateQueue(qd);

L'accesso in batch all'archivio non influisce sul numero di operazioni di messaggistica fatturabili ed è una proprietà di una coda, un argomento o una sottoscrizione. È indipendente dalla modalità di ricezione e dal protocollo utilizzato tra un client e il servizio di Service Bus.

Prelettura

La prelettura consente al client di coda o di sottoscrizione di caricare ulteriori messaggi dal servizio durante un'operazione di ricezione. Il client archivia questi messaggi in una cache locale. La dimensione della cache è determinata dalle proprietà PrefetchCount e PrefetchCount. Ogni client che abilita la prelettura gestisce la propria cache. Una cache non viene condivisa tra client. Se il client avvia un'operazione di ricezione e la relativa cache è vuota, il servizio trasmette un batch di messaggi. La dimensione del batch è uguale alla dimensione della cache o a 256 KB, a seconda di quale sia la dimensione inferiore. Se il client avvia un'operazione di ricezione e nella cache è contenuto un messaggio, il messaggio verrà recuperato dalla cache.

Quando un messaggio viene sottoposto a prelettura, il servizio lo blocca. In questo modo, il messaggio non potrà essere ricevuto da un altro ricevitore. Se il ricevitore non può completare il messaggio prima della scadenza del blocco, il messaggio diventa disponibile per altri ricevitori. La copia del messaggio sottoposta a prelettura resta nella cache. Il ricevitore che utilizza la copia scaduta memorizzata nella cache riceve un'eccezione quando tenta di completare il messaggio. Per impostazione predefinita, il blocco del messaggio scade dopo 60 secondi. Questo valore può essere esteso a 5 minuti. Per evitare che vengano utilizzati messaggi scaduti, la dimensione della cache dovrebbe essere sempre inferiore al numero di messaggi che possono essere utilizzati da un client nell'intervallo di timeout del blocco.

Se si utilizza l'impostazione predefinita di 60 secondi per la scadenza del blocco, è consigliabile impostare SubscriptionClient.PrefetchCount su un valore pari a 20 volte la velocità massima di elaborazione di tutti i ricevitori della factory. Si supponga ad esempio che una factory crei 3 ricevitori. Ogni ricevitore può elaborare fino a 10 messaggi al secondo. Il conteggio prelettura non deve superare 20*3*10 = 600. Per impostazione predefinita, la proprietà QueueClient.PrefetchCount è impostata su 0, a indicare che non vengono recuperati altri messaggi dal servizio.

La prelettura dei messaggi comporta un aumento della velocità effettiva globale per una coda o una sottoscrizione, poiché riduce il numero complessivo di operazioni sui messaggi, o round trip. Il recupero del primo messaggio tuttavia richiede più tempo (a causa della dimensione del messaggio aumentata). La ricezione di messaggi sottoposti a prelettura sarà più rapida, poiché questi messaggi sono stati già scaricati dal client.

La proprietà di durata (TTL) di un messaggio viene controllata dal server nel momento in cui invia il messaggio al client. Il client non controlla la proprietà TTL del messaggio al momento della ricezione. Il messaggio può essere ricevuto anche se la relativa durata (TTL) scade durante la memorizzazione nella cache da parte del client.

La prelettura non influisce sul numero di operazioni di messaggistica fatturabili ed è disponibile solo per il protocollo client di Service Bus. Il protocollo HTTP non supporta la prelettura. Questa funzionalità è disponibile per le operazioni di ricezione sincrone e asincrone.

Utilizzo di più code

Internamente, Service Bus utilizza lo stesso nodo per l'elaborazione di tutti i messaggi di un'entità. Per raggiungere una velocità effettiva superiore a diverse migliaia di messaggi al secondo, i messaggi devono essere distribuiti attraverso più entità. Si noti che tutte le sottoscrizioni di un argomento vengono gestite dallo stesso nodo che gestisce l'argomento. Se si utilizzano più entità, è consigliabile utilizzare un client dedicato per ciascuna anziché utilizzare lo stesso client per tutte.

Scenari

Nelle sezioni riportate di seguito vengono descritti scenari di messaggistica tipici e vengono illustrate le impostazioni di Service Bus preferite. La velocità effettiva è classificata come ridotta (<1 msg/s), moderata (≥1 msg/s, <100 msg/s) ed elevata (≥100 msg/s). Il numero di client è classificato come ridotto (≤5), moderato (>5, ≤20) ed elevato (>20).

Coda ad alta velocità effettiva

Obiettivo: aumentare la velocità effettiva di una singola coda. Il numero di mittenti e ricevitori è limitato.

  • Per aumentare la velocità di invio globale nella coda, utilizzare più factory di messaggistica per la creazione di mittenti. Per ciascun mittente, utilizzare operazioni asincrone o più thread.

  • Per aumentare la velocità di ricezione globale dalla coda, utilizzare più factory di messaggistica per la creazione di ricevitori.

  • Utilizzare operazioni asincrone per sfruttare i vantaggi dell'invio in batch sul lato client.

  • Impostare l'intervallo di invio in batch su 50 ms per ridurre il numero di trasmissioni tramite protocollo client di Service Bus. Se vengono utilizzati più mittenti, aumentare l'intervallo di invio in batch impostandolo su 100 ms.

  • Lasciare abilitato l'accesso in batch all'archivio. In questo modo aumenta la velocità complessiva con cui i messaggi possono essere scritti nella coda.

  • Impostare il conteggio prelettura su un valore pari a 20 volte la velocità di elaborazione massima di tutti i ricevitori di una factory. In questo modo viene ridotto il numero di trasmissioni tramite protocollo client di Service Bus.

Nei benchmark è possibile osservare che una singola coda può raggiungere una velocità effettiva massima dei messaggi di 2000 msg/s (dimensione dei messaggi: 1 KB). Per ottenere una velocità effettiva superiore, utilizzare più code.

Code multiple ad alta velocità effettiva

Obiettivo: aumentare la velocità effettiva complessiva di più code. La velocità effettiva di una singola coda è moderata o elevata.

Per ottenere la velocità effettiva massima su più code, utilizzare le impostazioni descritte per aumentare la velocità effettiva di una singola coda. Utilizzare inoltre factory diverse per creare client che inviano o ricevono da code diverse.

Coda a bassa latenza

Obiettivo: ridurre la latenza end-to-end di una coda o di un argomento. Il numero di mittenti e ricevitori è limitato. La velocità effettiva della coda è ridotta o moderata.

  • Disabilitare l'invio in batch sul lato client. Il client invia immediatamente un messaggio.

  • Disabilitare l'accesso in batch all'archivio. Il servizio scrive immediatamente il messaggio nell'archivio.

  • Se si utilizza un singolo client, impostare il conteggio prelettura su un valore pari a 20 volte la velocità di elaborazione del ricevitore. Se nella coda arrivano più messaggi contemporaneamente, il protocollo client di Service Bus li trasmette tutti insieme. Quando il client riceve il messaggio successivo, tale messaggio è già presente nella cache locale. La cache deve essere di dimensioni ridotte.

  • Se si utilizzano più client, impostare il conteggio prelettura su 0. In questo modo, il secondo client può ricevere il secondo messaggio mentre il primo client sta ancora elaborando il primo messaggio.

Coda con un numero elevato di mittenti

Obiettivo: aumentare la velocità effettiva di una coda o di un argomento con un numero elevato di mittenti. Ogni mittente invia messaggi con una velocità moderata. Il numero di ricevitori è limitato.

Service Bus abilita fino a un massimo di 100 connessioni simultanee a un'entità. Per le code, questo numero è condiviso tra mittenti e ricevitori. Se sono necessarie tutte e 100 le connessioni per i mittenti, è consigliabile sostituire la coda con un argomento e una singola sottoscrizione. Un argomento accetta fino a 100 connessioni simultanee dai mittenti, mentre la sottoscrizione accetta ulteriori 100 connessioni simultanee dai ricevitori. Se sono richiesti più di 100 mittenti simultanei, i mittenti devono inviare i messaggi al protocollo di Service Bus tramite HTTP.

Per ottimizzare la velocità effettiva, effettuare le seguenti operazioni:

  • Se ogni mittente si trova in un processo diverso, utilizzare solo una singola factory per processo.

  • Utilizzare operazioni asincrone per sfruttare i vantaggi dell'invio in batch sul lato client.

  • Utilizzare l'intervallo di invio in batch predefinito pari a 20 ms per ridurre il numero di trasmissioni tramite protocollo client di Service Bus.

  • Lasciare abilitato l'accesso in batch all'archivio. In questo modo aumenta la velocità complessiva con cui i messaggi possono essere scritti nella coda o nell'argomento.

  • Impostare il conteggio prelettura su un valore pari a 20 volte la velocità di elaborazione massima di tutti i ricevitori di una factory. In questo modo viene ridotto il numero di trasmissioni tramite protocollo client di Service Bus.

Coda con un numero elevato di ricevitori

Obiettivo: aumentare la velocità di ricezione di una coda o di una sottoscrizione con un numero elevato di ricevitori. Ogni ricevitore riceve messaggi a una velocità moderata. Il numero di mittenti è limitato.

Service Bus abilita fino a un massimo di 100 connessioni simultanee a un'entità. Se una coda richiede più di 100 ricevitori, è consigliabile sostituire la coda con un argomento e più sottoscrizioni. Ogni sottoscrizione può supportare fino a 100 connessioni simultanee. In alternativa, i ricevitori possono accedere alla coda tramite il protocollo HTTP.

Per ottimizzare la velocità effettiva, effettuare le seguenti operazioni:

  • Se ogni ricevitore si trova in un processo diverso, utilizzare solo una singola factory per processo.

  • I ricevitori possono utilizzare operazioni sincrone o asincrone. Data la velocità di ricezione moderata di un singolo ricevitore, l'invio in batch sul lato client di una richiesta Complete non influisce sulla velocità effettiva del ricevitore.

  • Lasciare abilitato l'accesso in batch all'archivio. In questo modo si riduce il carico complessivo dell'entità. Si riduce inoltre la velocità globale con cui i messaggi possono essere scritti nella coda o nell'argomento.

  • Impostare il conteggio prelettura su un valore ridotto, ad esempio PrefetchCount = 10. In questo modo si evita che i ricevitori rimangano inattivi mentre altri dispongono di un numero elevato di messaggi memorizzati nella cache.

Nei benchmark è possibile osservare che un singolo argomento con 5 sottoscrizioni può raggiungere una velocità effettiva massima dei messaggi di 600 msg/s (dimensione dei messaggi: 1 KB) se tutti i messaggi vengono instradati a tutte le sottoscrizioni. Per ottenere una velocità effettiva superiore, è necessario utilizzare più argomenti.

Argomento con un numero limitato di sottoscrizioni

Obiettivo: aumentare la velocità effettiva di un argomento con un numero limitato di sottoscrizioni. Poiché un messaggio viene ricevuto da molte sottoscrizioni, la velocità di ricezione combinata su tutte le sottoscrizioni è superiore alla velocità di invio. Il numero di mittenti è limitato. Il numero di ricevitori per sottoscrizione è limitato.

Per ottimizzare la velocità effettiva, effettuare le seguenti operazioni:

  • Per aumentare la velocità di invio globale nell'argomento, utilizzare più factory di messaggistica per la creazione di mittenti. Per ciascun mittente, utilizzare operazioni asincrone o più thread.

  • Per aumentare la velocità di ricezione globale di una sottoscrizione, utilizzare più factory di messaggistica per la creazione di ricevitori. Per ciascun ricevitore, utilizzare operazioni asincrone o più thread.

  • Utilizzare operazioni asincrone per sfruttare i vantaggi dell'invio in batch sul lato client.

  • Utilizzare l'intervallo di invio in batch predefinito pari a 20 ms per ridurre il numero di trasmissioni tramite protocollo client di Service Bus.

  • Lasciare abilitato l'accesso in batch all'archivio. In questo modo aumenta la velocità globale con cui i messaggi possono essere scritti nell'argomento.

  • Impostare il conteggio prelettura su un valore pari a 20 volte la velocità di elaborazione massima di tutti i ricevitori di una factory. In questo modo viene ridotto il numero di trasmissioni tramite protocollo client di Service Bus.

Nei benchmark è possibile osservare che un singolo argomento con 5 sottoscrizioni può raggiungere una velocità effettiva massima dei messaggi di 600 msg/s (dimensione dei messaggi: 1 KB) se tutti i messaggi vengono instradati a tutte le sottoscrizioni. Per ottenere una velocità effettiva superiore, utilizzare più argomenti.

Argomento con un numero elevato di sottoscrizioni

Obiettivo: aumentare la velocità effettiva di un argomento con un numero elevato di sottoscrizioni. Poiché un messaggio viene ricevuto da molte sottoscrizioni, la velocità di ricezione combinata su tutte le sottoscrizioni è superiore rispetto alla velocità di invio. Il numero di mittenti è limitato. Il numero di ricevitori per sottoscrizione è limitato.

Gli argomenti con un numero elevato di sottoscrizioni in genere espongono una velocità effettiva globale ridotta se tutti i messaggi vengono instradati a tutte le sottoscrizioni. Questo dipende dal fatto che ogni messaggio viene ricevuto più volte e che tutti i messaggi contenuti in un argomento e tutte le relative sottoscrizioni vengono archiviati nello stesso archivio. Si presuppone che il numero di mittenti e il numero di ricevitori per sottoscrizione sia ridotto. La versione di Service Bus di settembre 2011 supporta fino a 2.000 sottoscrizioni per argomento.

Per ottimizzare la velocità effettiva, effettuare le seguenti operazioni:

  • Utilizzare operazioni asincrone per sfruttare i vantaggi dell'invio in batch sul lato client.

  • Utilizzare l'intervallo di invio in batch predefinito pari a 20 ms per ridurre il numero di trasmissioni tramite protocollo client di Service Bus.

  • Lasciare abilitato l'accesso in batch all'archivio. In questo modo aumenta la velocità globale con cui i messaggi possono essere scritti nell'argomento.

  • Impostare il conteggio prelettura su un valore pari a 20 volte la velocità di ricezione prevista in secondi. In questo modo viene ridotto il numero di trasmissioni tramite protocollo client di Service Bus.

Nei benchmark è possibile osservare che un singolo argomento con 250 sottoscrizioni può raggiungere una velocità effettiva massima dei messaggi di 5 msg/s (dimensione dei messaggi: 1 KB) se tutti i messaggi vengono instradati a tutte le sottoscrizioni. Per ottenere una velocità effettiva superiore, utilizzare più argomenti.

Il documento è risultato utile?
(1500 caratteri rimanenti)

Aggiunte alla community

AGGIUNGI
© 2013 Microsoft. Tutti i diritti riservati.
facebook page visit twitter rss feed newsletter