[英]How to create Processor with Transaction and DLQ with Rabbit binding?
我才刚刚开始学习Spring Cloud Streams和Dataflow,我想了解一个重要的用例之一。 我创建了示例处理器Multiplier,它接收消息并将其重新发送5次以输出。
@EnableBinding(Processor.class)
public class MultiplierProcessor {
@Autowired
private Source source;
private int repeats = 5;
@Transactional
@StreamListener(Processor.INPUT)
public void handle(String payload) {
for (int i = 0; i < repeats; i++) {
if(i == 4) {
throw new RuntimeException("EXCEPTION");
}
source.output().send(new GenericMessage<>(payload));
}
}
}
您会看到在第5次发送此处理器之前崩溃。 为什么? 因为它可以(程序引发异常)。 在这种情况下,我想在Spring Cloud Stream上练习故障预防。
我要实现的是将输入消息备份到DLQ中,并发送4条消息,这些消息在发送之前已还原并且不被下一个操作数使用(就像在普通JMS事务中一样)。 我已经尝试在处理器项目中定义以下属性,但没有成功。
spring.cloud.stream.bindings.output.producer.autoBindDlq=true
spring.cloud.stream.bindings.output.producer.republishToDlq=true
spring.cloud.stream.bindings.output.producer.transacted=true
spring.cloud.stream.bindings.input.consumer.autoBindDlq=true
你能告诉我是否可能,还有我在做什么错? 对于某些示例,我将非常感激。
您的配置有几个问题:
.rabbit
) autoBindDlq
autoBindDlq
不适用于输出端 消费者必须进行交易,以便生产者发送在同一事务中执行。
我刚刚用1.0.2.RELEASE测试过:
spring.cloud.stream.bindings.output.destination=so8400out
spring.cloud.stream.rabbit.bindings.output.producer.transacted=true
spring.cloud.stream.bindings.input.destination=so8400in
spring.cloud.stream.bindings.input.group=so8400
spring.cloud.stream.rabbit.bindings.input.consumer.durableSubscription=true
spring.cloud.stream.rabbit.bindings.input.consumer.autoBindDlq=true
spring.cloud.stream.rabbit.bindings.input.consumer.transacted=true
并按预期工作。
编辑
实际上,不,发布的邮件不会回滚。 调查...
EDIT2
好; 它确实有效,但是您不能使用republishToDlq
因为启用该功能后,绑定程序会将失败的消息发布到DLQ并提交事务。
如果为假,则将异常引发到容器,回滚事务,然后RabbitMQ将失败的消息移至DLQ。
但是请注意,默认情况下会启用重试(3次尝试),因此,如果处理器在重试期间成功,则输出中将出现重复项。
为了使此功能如您所愿,您需要通过将最大尝试次数设置为1来禁用重试(并且不要使用republishToDlq
)。
EDIT3
好的,如果您想更好地控制错误的发布,则当此JIRA的修复程序应用于Spring AMQP时,此方法将起作用。
@SpringBootApplication
@EnableBinding({ Processor.class, So39018400Application.Errors.class })
public class So39018400Application {
public static void main(String[] args) {
SpringApplication.run(So39018400Application.class, args);
}
@Bean
public Foo foo() {
return new Foo();
}
public interface Errors {
@Output("errors")
MessageChannel errorChannel();
}
private static class Foo {
@Autowired
Source source;
@Autowired
Errors errors;
@StreamListener(Processor.INPUT)
public void handle (Message<byte[]> in) {
try {
source.output().send(new GenericMessage<>("foo"));
source.output().send(new GenericMessage<>("foo"));
throw new RuntimeException("foo");
}
catch (RuntimeException e) {
errors.errorChannel().send(MessageBuilder.fromMessage(in)
.setHeader("foo", "bar") // add whatever you want, stack trace etc.
.build());
throw e;
}
}
}
}
具有属性:
spring.cloud.stream.bindings.output.destination=so8400out
spring.cloud.stream.bindings.errors.destination=so8400errors
spring.cloud.stream.rabbit.bindings.errors.producer.transacted=false
spring.cloud.stream.rabbit.bindings.output.producer.transacted=true
spring.cloud.stream.bindings.input.destination=so8400in
spring.cloud.stream.bindings.input.group=so8400
spring.cloud.stream.rabbit.bindings.input.consumer.transacted=true
spring.cloud.stream.rabbit.bindings.input.consumer.requeue-rejected=false
spring.cloud.stream.bindings.input.consumer.max-attempts=1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.