2015-06-07 23 views
12

in questa guida https://www.rabbitmq.com/api-guide.html RabbitMQ Stato ragazzi:RabbitMQ e canali filo di sicurezza Java

Canali e considerazioni Concorrenza (thread-safe) casi

canale non deve essere condiviso tra i thread. Le applicazioni dovrebbero preferire l'uso di un canale per thread invece di condividere lo stesso canale su più thread. Mentre alcune operazioni sui canali sono sicure da richiamare contemporaneamente, alcune non lo sono e generano un interleaving della trama errato sul filo. La condivisione di canali tra thread interferirà anche con * Conferme Publisher.

sicurezza Discussione è molto importante così ho cercato di essere il più diligente possibile, ma ecco il problema:

Ho questa applicazione che riceve i messaggi da coniglio. Quando viene ricevuto un messaggio, lo elabora e poi lo fa quando viene terminato. L'applicazione può elaborare solo 2 elementi contemporaneamente in un pool di thread fisso con 2 thread. Il prefetch di QOS per Rabbit è impostato su 2, perché non voglio alimentare l'app con più di quanto possa gestire in un intervallo di tempo.

Ora, handleDelivery di mia consumatore effettua le seguenti operazioni:

Task run = new Task(JSON.parse(message));  
service.execute(new TestWrapperThread(getChannel(),run,envelope.getDeliveryTag())); 

A questo punto, è già capito che TestWrapperThread fa la chiamata channel.basicAck(deliveryTag, false); come ultima operazione.

Dalla mia comprensione della documentazione, questo è errato e potenzialmente dannoso perché il canale non è thread-safe e questo comportamento potrebbe rovinare tutto. Ma come dovrei fare allora? Voglio dire, ho qualche idea, ma loro renderebbero tutto più complesso e mi piacerebbe capirlo se è davvero necessario o no.

Grazie in anticipo

+0

Se ho capito, la tua domanda riguarda il multithreading channel.basicAck (deliveryTag, false); è giusto? – Gabriele

+0

corretto. Questa è la mia unica preoccupazione –

risposta

10

suppongo che si sta utilizzando Channel solo per il vostro consumatore e non per altre operazioni piace pubblicare ecc ..

Nel tuo caso l'unico potenziale problema è qui:

channel.basicAck(deliveryTag, false); 

perché lo chiamate attraverso due thread, btw questa operazione è sicura, se vedi il codice java:

the clas s ChannelN.java chiamate:

public void basicAck(long deliveryTag, boolean multiple) 
    throws IOException 
{ 
    transmit(new Basic.Ack(deliveryTag, multiple)); 
} 

see github code for ChannelN.java

metodo transmit all'interno AMQChannel usi:

public void transmit(Method m) throws IOException { 
    synchronized (_channelMutex) { 
     transmit(new AMQCommand(m)); 
    } 
} 

_channelMutex è un protected final Object _channelMutex = new Object();

creato con la classe. see github code for AMQChannel.java

EDIT

Come si può leggere sul documentazione ufficiale, "alcune" operazioni sono thread-safe, ora non è chiaro quali. Ho studiato il codice, penso che non ci siano problemi nel chiamare l'ACK su più thread.

Spero che aiuti.

EDIT2 aggiungo anche il commento di Nicolas:

nota che il consumo (basicConsume) e ACKing da più di un thread è un modello RabbitMQ comune che viene già utilizzato dal client java.

Quindi è possibile utilizzarlo in sicurezza.

+0

Solo il consumatore. Quindi stai sostanzialmente confermando che non dovrebbe essere un problema? Pensi che la documentazione in realtà significhi "essere infallibile in situazioni di ricezione/invio promiscue"? –

+0

Grazie Gas. Penso di avere una teoria sul perché sostengono sostanzialmente che non si dovrebbe usare il multi-thread di un canale, menzionando esplicitamente anche l'operazione di riconoscimento. Penso che il problema sia che usi in modo massiccio il canale in vari thread, in operazioni di invio di grandi quantità di dati, in pratica blocchi il canale fino a quando non sono terminati. Ora, se è necessario inviare nuovamente i riconoscimenti, potrebbero ritardare molto, probabilmente facendo in modo che il sistema attivi le procedure di "recupero" quando non è effettivamente necessario. –

+1

Si noti che il consumo (basicConsume) e l'accesso da più thread è un pattern rabbitmq comune già utilizzato dal client java. –

Problemi correlati