2011-01-19 12 views
35

Desidero inviare un batch di messaggi JMS 20k a una stessa coda. Sto suddividendo il compito usando 10 thread, quindi ognuno elaborerà i messaggi 2k. Non ho bisogno di transazioni.Relazione tra connessioni JMS, sessioni e produttori/consumatori

Mi chiedevo se avere una connessione, una sessione e 10 produttori è il modo migliore per andare o no?

E se avessi un produttore condiviso da tutti i thread? I miei messaggi sarebbero corrotti o verrebbero inviati sincronizzati (non dando alcun guadagno in termini di prestazioni)?

Qual è la linea guida generale per decidere se creare una nuova connessione o sessione se mi collego sempre alla stessa coda?

Grazie e scusa per aver chiesto molto in una volta.

(Ecco una domanda simile, ma non ha abbastanza risposto quello che stavo cercando. Long lived JMS sessions. Is Keeping JMS connections/JMS sessions allways open a bad pratice?)

risposta

24

Va bene se alcuni messaggi sono duplicati o persi? Quando il client JMS si connette al broker JMS sulla rete, ci sono tre fasi per ogni chiamata API.

  1. La chiamata API, inclusi i dati dei messaggi, viene trasmessa sul filo al broker.
  2. La chiamata API viene eseguita dal broker.
  3. Il codice risultato e tutti i dati dei messaggi vengono trasmessi al client.

Considerare il produttore per un minuto. Se la connessione viene interrotta nel primo passaggio, il broker non ha mai ricevuto il messaggio e l'app dovrà inviarlo di nuovo. Se la connessione viene interrotta nel terzo passaggio, il messaggio è stato inviato correttamente e l'invio di nuovo produrrebbe un messaggio duplicato. L'app non può dire la differenza tra questi e quindi l'unica scelta sicura è di inviare nuovamente il messaggio in caso di errore. Se la sessione viene trasferita, il messaggio può essere risentito in tutti i casi in modo sicuro, perché se l'originale è stato inoltrato al broker, verrà eseguito il rollback.

Considerare il consumatore. Se la connessione viene persa nel terzo passaggio, il messaggio viene eliminato dalla coda ma non viene mai restituito al client. Ma se la sessione viene trasferita, il messaggio verrà riconsegnato quando l'applicazione si riconnetterà.

Al di fuori delle transazioni c'è la possibilità di messaggi persi o duplicati. All'interno di una transazione esiste la stessa finestra di ambiguità ma è sulla chiamata COMMIT piuttosto che su PUT o GET. Con sessioni transate è possibile inviare o ricevere un messaggio due volte ma non perderne uno.

Il JMS spec riconosce questa finestra di ambiguità e fornisce le seguenti linee guida:

Se si verifica un guasto tra momento in cui un cliente si impegna il suo lavoro su una sessione e l' ritorna metodo commit, il client impossibile determinare se la transazione è stata confermata o annullato. La stessa ambiguità esiste quando si verifica un errore tra l'invio non transazionale di un messaggio PERSISTENT e il ritorno dal metodo di invio .

Spetta a un'applicazione JMS occuparsi di con questa ambiguità. In alcuni casi, ciò potrebbe causare la duplicazione dei messaggi da parte di un client per produrre .

Un messaggio che viene riconsegnato a causa del recupero della sessione non è considerato un messaggio duplicato .

Le sessioni JMS devono sempre essere gestite, ad eccezione dei casi in cui è davvero corretto perdere i messaggi. Se le sessioni vengono eseguite, è necessario disporre della sessione e della connessione per-thread a causa del modello di thread JMS.

Qualsiasi consiglio sugli impatti delle prestazioni sarebbe specifico del fornitore, ma in generale i messaggi persistenti al di fuori del punto di sincronizzazione vengono induriti su disco prima che la chiamata API ritorni. Ma una chiamata gestita può tornare prima che il messaggio persistente venga scritto sul disco a condizione che il messaggio venga mantenuto prima che COMMIT restituisca. Se il fornitore ottimizza in base a ciò, è molto più performante scrivere diversi messaggi su disco e quindi eseguirne il commit in batch. Ciò consente al broker di ottimizzare scritture e svuotamenti del disco per blocco del disco anziché per messaggio. Il numero di messaggi da inserire nella transazione diminuisce con la dimensione del messaggio e oltre una determinata dimensione del messaggio si riduce a uno.

Se i messaggi di 20k sono relativamente piccoli (misurati in k e non in mb), probabilmente si desidera utilizzare sessioni transulate per thread e ottimizzare l'intervallo di commit.

1

In Connessioni di teoria sono thread-safe, ma tutti gli altri non sono, così si dovrebbe creare una seduta al filo.

In realtà, dipende dall'implementazione JMS che si sta utilizzando.

9

Nella maggior parte degli scenari è sufficiente lavorare con una connessione e più sessioni, utilizzando una sessione per thread. In alcuni ambienti è possibile ottenere prestazioni aggiuntive utilizzando più connessioni:

Alcuni sistemi di messaggistica supportano una modalità cluster, in cui le connessioni vengono loadbalanced su nodi diversi. Con più connessioni è possibile utilizzare le prestazioni di più nodi in questo scenario. (che ovviamente aiuta solo quando il collo di bottiglia si trova sul lato del broker dei messaggi).

La soluzione migliore sarebbe per noi un pool di connessioni e fornire all'amministratore alcune opzioni per configurare il comportamento nell'area specifica.

3
I was wondering if having one connection, one session, and 10 producers 
is the recommended way to go or not? 

Certo, ma il punto da notare qui è che si sta utilizzando un solo thread solo quello che si crea durante la creazione dell'oggetto Session. Tutti e 10 i produttori sono legati a questo oggetto di sessione e di conseguenza allo stesso thread.

How about if I had one producer shared by all the threads? Would my messages 
be corrupt or would it be sent out synchronized (giving no performance gain)? 

Pessima idea, direi. Le specifiche JMS dicono chiaramente che Session non dovrebbe essere condivisa da più di un thread. Non è thread-safe.

What's the general guideline of deciding whether to create a new connection 
or session if I'm always connecting to the same queue? 

Se il sistema supporta il multithreading, è possibile creare più sessioni (ciascuna sessione corrisponde a un singolo thread) da una singola connessione. Ogni sessione di può avere più produttori/consumatori, ma tutti questi non devono essere condivisi tra thread.

4

Da ciò che indago su questo argomento, una sessione indica un thread. Questo è basato su specifiche JMS. Se si desidera il threading multiplo (più produttori/consumatori), è necessario creare più sessioni, una connessione va bene.