我不熟悉Azure Service Bus,我正在使用Java SDK开发示例发布/订阅应用程序。在本练习中,我想要实现的是将50条消息(json)发布到队列中,这些消息采用以下格式。
[{'lastname'='test0','firstName'='success0'} ...'lastname'='test49','firstName'='success49'}]
在第25条消息的接收方应用程序中,我希望放弃此消息,因此第25条消息将在队列中可用。但是当我运行应用程序时,所有49条消息均已完成,其中一条消息发送到 死信队列。我没有例外。
Either receive link to 'asb.java.pub' closed with a transient error and reopened or the delivery was already settled by complete/abandon/defer/deadletter.
2019-05-09 06:17:19 ERROR MessageAndSessionPump:241 - Completing message with sequence number '5002' failed
java.lang.IllegalArgumentException: Delivery not found on the receive link.
at com.geico.messaging.servicebus.primitives.CoreMessageReceiver.generateDeliveryNotFoundException(CoreMessageReceiver.java:1319)
at com.geico.messaging.servicebus.primitives.CoreMessageReceiver.updateMessageStateAsync(CoreMessageReceiver.java:1161)
at com.geico.messaging.servicebus.primitives.CoreMessageReceiver.completeMessageAsync(CoreMessageReceiver.java:1046)
at com.geico.messaging.servicebus.MessageReceiver.lambda$3(MessageReceiver.java:267)
at java.util.concurrent.CompletableFuture.uniComposeStage(Unknown Source)
at java.util.concurrent.CompletableFuture.thenCompose(Unknown Source)
at com.geico.messaging.servicebus.MessageReceiver.completeAsync(MessageReceiver.java:262)
at com.geico.messaging.servicebus.MessageReceiver.completeAsync(MessageReceiver.java:255)
at com.geico.messaging.servicebus.MessageAndSessionPump.lambda$6(MessageAndSessionPump.java:220)
at java.util.concurrent.CompletableFuture.uniHandle(Unknown Source)
at java.util.concurrent.CompletableFuture$UniHandle.tryFire(Unknown Source)
at java.util.concurrent.CompletableFuture$Completion.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
。这是我的发布代码
ConnectionStringBuilder connectionResolver = new ConnectionStringBuilder(connectionString, "asb.java.pub");
QueueClient sendClient = new QueueClient(connectionResolver,ReceiveMode.PEEKLOCK);
for(int i =0;i<50;i++){Message message = new Message("{'lastname' = 'test"+i+"', 'firstName' ='success"+i+"'}");
message.setLabel("name");sendClient.send(message);}sendClient.close();
这是我的订户代码
IMessageHandler ih=new IMessageHandler() {
public CompletableFuture<Void> onMessageAsync(IMessage message) {
byte[] body = message.getBody();
Map map = GSON.fromJson(new String(body, UTF_8), Map.class);
try{ if(map.get("lastname").equals("test25")){ return receiveClient.abandonAsync(message.getLockToken());
;
}catch(Exception e){ e.printStackTrace();
}
CompletableFuture.completedFuture(null);
}
public void notifyException(Throwable throwable, ExceptionPhase exceptionPhase) {
System.out.printf(exceptionPhase + "-" + throwable.getMessage());
}
};
receiveClient.registerMessageHandler(ih, executorService);
以下是运行发布应用enter image description here
后的屏幕截图运行订阅者应用后的以下屏幕截图。enter image description here
我的问题是为什么当我调用放弃方法时,消息会进入Deadletter。我不能使特定消息放弃或自动完成为false。这样该消息将在队列中可用。
谢谢。
答案 0 :(得分:0)
看起来像预期的行为。放弃消息时,传递计数将增加1,并且消息在队列中再次可用以进行处理。但是,如果您继续放弃邮件,则传递计数将达到最大限制(从屏幕截图中为10),然后将邮件移至死信队列。
要获得更好的主意,请查看交易信队列中的消息并确定失败的原因。您可以在服务总线资源管理器中进行操作。
答案 1 :(得分:0)
只需替换为一个以下
receiveClient.registerMessageHandler(ih, new MessageHandlerOptions(1,true, Duration.ofMinutes(1)),executorService);