[英]Manual Acknowledgement of ActiveMQ Messages with Alpakka
I am working on implementing Akka Alpakka for consuming from and producing to ActiveMQ queues, in Java. 我正在努力实现Akka Alpakka,以便在Java中使用和生成ActiveMQ队列。 I can consume from the queue successfully, but I haven't yet been able to implement application-level message acknowledgement.
我可以成功地从队列中消耗,但我还没有能够实现应用程序级消息确认。
My goal is to consume messages from a queue and send them to another actor for processing. 我的目标是使用队列中的消息并将它们发送给另一个actor进行处理。 When that actor has completed processing, I want it to be able control the acknowledgement of the message in ActiveMQ.
当该actor完成处理时,我希望它能够控制ActiveMQ中的消息确认。 Presumably this would be done by sending a message to another actor that can do the acknowledgement, calling an acknowledge function on the message itself, or some other way.
据推测,这可以通过向另一个可以进行确认的actor发送消息,在消息本身上调用确认函数或其他方式来完成。
In my test, 2 messages are put into the AlpakkaTest queue, and then this code attempts to consume and acknowledge them. 在我的测试中,将2条消息放入AlpakkaTest队列,然后此代码尝试使用并确认它们。 However, I don't see a way to set the ActiveMQ session to CLIENT_ACKNOWLEDGE, and I don't see any difference in behavior with or without the call to
m.acknowledge();
但是,我没有看到将ActiveMQ会话设置为CLIENT_ACKNOWLEDGE的方法,并且我没有看到有或没有调用
m.acknowledge();
行为有任何差异m.acknowledge();
. 。 Because of this, I think messages are still being auto-acknowledged.
因此,我认为消息仍然是自动确认的。
Does anyone know the accepted way to configure ActiveMQ sessions for CLIENT_ACKNOWLEDGE and manually acknowledge ActiveMQ messages in Java Akka systems using Alpakka? 有没有人知道为CLIENT_ACKNOWLEDGE配置ActiveMQ会话的可接受方式,并使用Alpakka在Java Akka系统中手动确认ActiveMQ消息?
The relevant test function is: 相关测试功能是:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://0.0.0.0:2999"); // An embedded broker running in the test.
Source<Message, NotUsed> jmsSource = JmsSource.create(
JmsSourceSettings.create(connectionFactory)
.withQueue("AlpakkaTest")
.withBufferSize(2)
);
Materializer materializer = ActorMaterializer.create(system); // `system` is an ActorSystem passed to the function.
try {
List<Message> messages = jmsSource
.take(2)
.runWith(Sink.seq(), materializer)
.toCompletableFuture().get(4, TimeUnit.SECONDS);
for(Message m:messages) {
System.out.println("Found Message ID: " + m.getJMSMessageID());
try {
m.acknowledge();
} catch(JMSException jmsException) {
System.out.println("Acknowledgement Failed for Message ID: " + m.getJMSMessageID() + " (" + jmsException.getLocalizedMessage() + ")");
}
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
} catch (TimeoutException e1) {
e1.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
}
This code prints: 此代码打印:
Found Message ID: ID:jmstest-43178-1503343061195-1:26:1:1:1
Found Message ID: ID:jmstest-43178-1503343061195-1:27:1:1:1
Update : The acknowledgement mode is configurable in the JMS connector since Alpakka 0.15 . 更新 :自Alpakka 0.15起,确认模式可在JMS连接器中配置。 From the linked documentation:
从链接的文档:
Source<Message, NotUsed> jmsSource = JmsSource.create(JmsSourceSettings
.create(connectionFactory)
.withQueue("test")
.withAcknowledgeMode(AcknowledgeMode.ClientAcknowledge())
);
CompletionStage<List<String>> result = jmsSource
.take(msgsIn.size())
.map(message -> {
String text = ((ActiveMQTextMessage)message).getText();
message.acknowledge();
return text;
})
.runWith(Sink.seq(), materializer);
As of version 0.11, Alpakka's JMS connector does not support application-level message acknowledgment. 从版本0.11开始,Alpakka的JMS连接器不支持应用程序级消息确认。 Alpakka creates internally a
Session
with the CLIENT_ACKNOWLEDGE
mode here and acknowledges each message here in the internal MessageListener
. Alpakka内部创建一个
Session
与CLIENT_ACKNOWLEDGE
模式这里并确认每个消息这里在内部MessageListener
。 The API does not expose these settings for overriding. API不会公开这些设置以进行覆盖。
There is an open ticket that discusses enabling downstream acknowledgement of queue-based sources, but that ticket has been inactive for a while. 有一个打开的故障单 ,讨论启用下游确认基于队列的源,但该故障单已暂停一段时间。
Currently you cannot prevent Alpakka from acknowledging the messages at the JMS level. 目前,您无法阻止Alpakka在JMS级别确认消息。 However, that doesn't preclude you from adding a stage to your stream that sends each message to an actor for processing and uses the actor's replies as backpressure signals.
但是,这并不妨碍您向流添加一个阶段,该阶段将每个消息发送给actor进行处理,并将actor的回复用作背压信号。 The Akka Streams documentation describes how to do this with either a combination of
mapAsync
and ask
or with Sink.actorRefWithAck
. Akka Streams 文档描述了如何使用
mapAsync
和ask
或Sink.actorRefWithAck
的组合来完成此Sink.actorRefWithAck
。 For example, to use the former: 例如,要使用前者:
Timeout askTimeout = Timeout.apply(4, TimeUnit.SECONDS);
jmsSource
.mapAsync(2, msg -> ask(processorActor, msg, askTimeout))
.runWith(Sink.seq(), materializer);
(Side note: In the related Streamz project, there is a recently opened ticket to allow application-level acknowledgement. Streamz is the replacement for the old akka-camel module and, like Alpakka, is built on Akka Streams. Streamz also has a Java API and is listed in the Alpakka documentation as an external connector.) (附注:在相关的Streamz项目中,有一个最近打开的票证允许应用程序级别确认.Streamz是旧的akka-camel模块的替代品,和Alpakka一样,是基于Akka Streams构建的.Streamz也有一个Java API并列出所述文档Alpakka作为外部连接器)。
Looking at the source code for the Alpakka JmsSourceStage it already acknowledges each incoming message for you (and it's session is a Client Ack session). 查看Alpakka JmsSourceStage的源代码,它已经为您确认了每个传入消息(并且它的会话是Client Ack会话)。 From what I can tell from the source there is no mode that allows you to do the acknowledgement of messages.
从我从源头上可以看出,没有允许你对消息进行确认的模式。
You can view the source code for Alpakka here . 您可以在此处查看Alpakka的源代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.