我们为特定用例实现了分布式请求/响应类型架构,我们希望等待响应。我们使用的JMS代理是ActiveMq,代码使用Spring连接在一起。
我们看到的问题是,如果将一堆请求发送到同一目的地,任何请求(例如,需要花费大量时间才能完成),则会阻止其后的请求消息。使用者使用的SessionAwareMessageListener接口仅支持onMessage()方法。在这里实现并行性的最佳方法是什么,即如果特定请求需要很长时间,队列中的其他消息不应被阻止?
有这个SO帖子,但它没有回答我的问题。 JMS: Can we get multiple messages from queue in OnMessage() withtout commit or rollback
由于
相关的代码片段(为简洁起见,删除了异常处理等)
生产者
public class MyJmsProducer {
private ProcessingResponse sendMessage(final Serializable serializable) {
//send JMS request and wait for response
return jmsMessagingTemplate.convertSendAndReceive(destination, serializable, ProcessingResponse.class); //this operation seems to be blocking + sync
}
}
听众(消费者)
public class MyJmsListener
implements SessionAwareMessageListener<Message>, NotificationHandler<Task> {
@Override
public void onMessage(Message message, Session session)
throws JMSException {
ProcessingRequest processingRequest = (ProcessingRequest) ((ObjectMessage) message).getObject();
// handle the request here (THIS COULD TAKE A WHILE)
handleRequest(processingRequest);
// done handling the request, now create a response message
final ObjectMessage responseMessage = new ActiveMQObjectMessage();
responseMessage.setJMSCorrelationID(message.getJMSCorrelationID());
responseMessage.setObject(processingResponse);
// Message sent back to the replyTo address of the income message.
final MessageProducer producer = session.createProducer(message.getJMSReplyTo());
producer.send(responseMessage);
}
}
答案 0 :(得分:2)
您可以使用DMLC的ConcurrentConsumers
来提高消息的消费速度并解决消费者缓慢的问题:
@Bean
public DefaultMessageListenerContainer dmlc() {
DefaultMessageListenerContainer dmlc = new DefaultMessageListenerContainer();
dmlc.setMaxConcurrentConsumers(10);
dmlc.setConcurrentConsumers(5);
return dmlc;
}
您需要将prefetchPolicy调整为Concurrent Consumers:
persistent queues (default value: 1000)
non-persistent queues (default value: 1000)
persistent topics (default value: 100)
non-persistent topics (default value: Short.MAX_VALUE - 1)
将所有消息分派给第一个连接的使用者,当另一个消息连接到同一目标时,他不接收消息,因此要更改此行为,您需要将prefetchPolicy设置为低于默认值的值。例如,将此jms.prefetchPolicy.queuePrefetch=1
添加到activemq.xml中的uri配置中,或者将其设置在客户端URL上,如下所示
@Bean
public ConnectionFactory connectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
"tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1");
return connectionFactory;
}
建议使用较大的预取值以获得较高的高性能 消息卷。但是,对于较低的消息量,每个消息量 消息需要很长时间才能处理,预取应该设置为1。 这可确保消费者一次只处理一条消息。 但是,将预取限制指定为零将导致使用者 一次一个地轮询消息,而不是消息 推向消费者。
查看http://activemq.apache.org/what-is-the-prefetch-limit-for.html
并且