我有独立的MQ侦听器,它侦听队列。在onMessage()中处理响应的最佳方法是什么。我不希望我的业务逻辑出现在onMessage()中。另外,我不希望onMessage()等待解析响应并存储在DB中。
public abstract class MQReceiver implements MessageListener{
public void pollResults(Long counter) throws JMSException, InterruptedException {
Queue rQueue = null;
QueueSession session = null;
QueueReceiver receiver;
count = counter;
try{
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
rQueue = session.createQueue(getReceiveQueue());
receiver = session.createReceiver(rQueue);
receiver.setMessageListener(this);
connection.start();
while(count > 0){
logger.info("Waiting......Count >> " + count);
Thread.sleep(SLEEPTIME);
}
if(count == 0){
session.close();
logger.info("exiting poll results");
}
}finally{
if(session != null)
session.close();
}
}
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
//Parse and Apply business logic
//Store in DB
}
}
答案 0 :(得分:0)
如果您不想等待业务逻辑和数据库交互,那么您可能会离开另一个线程并返回。
但请注意,如果你离开另一个线程,你将失去对它的异常控制权。
我认为你可以从java 8中的CompletableFuture
开始:
YourOffworkService service;
....
public void onMessage(Message msg){
if (message instance of TextMessage) {
CompletableFuture.runAsync(() -> { service.process(msg);});
}
}
修改强>
在java 7中,您可以Thread
或Runnable
public class YourOffworkService extends Thread {
private Message message;
public YourOffworkService(Message message) {
this.message = message;
}
public void run() {
// Here come the business logic / DB interaction
}
}
然后在onMessage()
:
public void onMessage(Message msg) {
...bla bla...
new YourOffworkService(msg).start();
}
答案 1 :(得分:0)
但是为什么你不希望OnMessage线程等你完成你的工作?这几乎是消息传递系统的目的。如果由于某些错误而无法插入到DB中,则将回滚该消息并且不会丢失 - 并且可以尝试第二次尝试。如果在其他地方卸载逻辑/数据库操作,则会失去容错能力。
无论如何,最好的方法不是从OnMessage生成线程或类似的东西,而是将消息排入某个内部队列,这是由工作线程读取的。如果您只是启动线程,则在启动时处理队列中的数千条消息时会遇到问题。为此,Java有一个很好的BlockingQueue。这样你就可以控制多少线程应该忙着做逻辑/数据库的东西。在需要等到后端可以跟上之前,您需要在某处限制可以从ActiveMQ读取的消息数量。队列是一种很好的方法。
阻止队列的示例。
final BlockingQueue<String> internalQueue = new ArrayBlockingQueue<String>(CAPACITY);
...
new Thread(new Runnable() { // TODO make a named class and schedule as many thread as needed.
@Override public void run() {
try {
while (true) {
String msg = internalQueue.take();
System.out.println(msg);
}
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
}
}).start();
...
public void onMessage(Message message) {
if (message instanceof TextMessage) {
internalQueue.put(((TextMessage)message).getText());
}
}
无论如何,当你再考虑一次时,那么将队列保留在ActiveMQ中是不是更好?如果该过程太耗时,请考虑将流程分成多个步骤,并在其间排队。
示例: