问题
I am using the bundled JMS implementation on Wildfly 8.1 (HornetQ) to OCR a large number of documents.
I want to have a pool of 3 MDBs consuming the messages of a Queue with the documents to be OCRed. Each MDB starts a process with the Apache commons-exec and blocks until that process exits.
In my test I have 50 JMS messages (each represents a document to be OCRed) which are loaded on the Queue at the beginning of the test. When the processing starts, at any given time I can see that there are 3 CPU intensive OCR processes, one started and blocked upon by each MDB. At some point, after 20 minutes or so, one of the OCR processes dissappears, and only 2 remain alive at any given time. When there are 10 JMS messages or so remaining, another OCR process stops, and there is only 1 at any given time.
In the end, all 50 documents have been OCRed, and no exception is being thrown by any of the OCR processes or my application.
I find this behaviour strange because I would expect that there would be 3 OCR processes alive at any point in time consuming JMS messages (except at the end of course). This behaviour could be explained if the JMS messages are "assigned" to the MDB instances upon entry in the Queue, and not real time. For instance, if each MDB was assigned around 17 messages. Depending on the document sizes, some MDB instances could finish earlier and stay idle without consuming any other messages, when the other MDB instances could still have messages to consume.
Is this what is happening? If yes, is there a way to change this so that the assignment of messages to MDB instances happens whenever an MDB instance finishes processing a message?
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/csrOcrQueue"),
@ActivationConfigProperty(propertyName = "minSession", propertyValue = "3"),
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "3")
})
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class OcrMessageListener implements MessageListener {
回答1:
This has to do with JMS message buffering on the client (MDB). Message buffering is by default turned on to avoid network latency. However, for my case where I have slow clients, this is't a problem.
This is from the HornetQ documentation:
11.1.39. No Consumer Buffering
By default, HornetQ consumers buffer messages from the server in a client side buffer before you actually receive them on the client side. This improves performance since otherwise every time you called receive() or had processed the last message in a MessageListener onMessage() method, the HornetQ client would have to go the server to request the next message, which would then get sent to the client side, if one was available.
This would involve a network round trip for every message and reduce performance. Therefore, by default, HornetQ pre-fetches messages into a buffer on each consumer.
In some case buffering is not desirable, and HornetQ allows it to be switched off. This example demonstrates that.
There is a sample project in Github as part of the documentation, where consumer buffering is turned off: link
来源:https://stackoverflow.com/questions/25245299/wildfly-jms-mdb-beans-idle-when-messages-exist