我正在从服务(S)接收消息,该服务将每个单独的属性更改作为单独的消息发布到实体.一个人为的例子是这样的实体:
Person {
id: 123
name: "Something",
address: {...}
}
如果在同一事务中更新了名称和地址,则(S)将发布两条消息,即PersonNameCorrected和PersonMoved.问题出在接收方,我正在存储此Person实体的投影,并且每个属性更改都会导致对数据库的写入.因此,在此示例中,将有两次写入数据库的操作,但是如果我可以在短时间内批处理消息并将其按ID分组,则只需对数据库进行一次写入操作.
通常在RabbitMQ中如何处理此问题? Spring AMQP是否提供更简单的抽象?
请注意,我已经简要地看了prefetch,但是我不确定这是否可行.如果我理解正确,则预取也是基于每个连接的.我正在尝试基于每个队列实现此目标,因为如果要采用批处理(并因此增加延迟),则我不想将此延迟添加到我的服务消耗的所有队列中(但仅添加到那些需要“按ID分组”功能).
解决方法:
对于这种情况,预取将无济于事.
考虑使用Spring Integration,它的适配器位于Spring AMQP的顶部;它还提供了一个聚集器,可用于将消息分组在一起,然后再将其发送到管道的下一个阶段.
编辑
这是一个演示的快速启动应用程序…
@SpringBootApplication
public class So42969130Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(So42969130Application.class, args)
.close();
}
@Autowired
private RabbitTemplate template;
@Autowired
private Handler handler;
@Override
public void run(String... args) throws Exception {
this.template.convertAndSend("so9130", new PersonNameChanged(123));
this.template.convertAndSend("so9130", new PersonMoved(123));
this.handler.latch.await(10, TimeUnit.SECONDS);
}
@Bean
public IntegrationFlow flow(ConnectionFactory connectionFactory) {
return IntegrationFlows.from(Amqp.inboundAdapter(connectionFactory, "so9130")
.messageConverter(converter()))
.aggregate(a -> a
.correlationExpression("payload.id")
.releaseExpression("false") // open-ended release, timeout only
.sendPartialResultOnExpiry(true)
.groupTimeout(2000))
.handle(handler())
.get();
}
@Bean
public Jackson2JsonMessageConverter converter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public Handler handler() {
return new Handler();
}
@Bean
public Queue queue() {
return new Queue("so9130", false, false, true);
}
public static class Handler {
private final CountDownLatch latch = new CountDownLatch(1);
@ServiceActivator
public void handle(Collection> aggregatedData) {
System.out.println(aggregatedData);
this.latch.countDown();
}
}
public static class PersonNameChanged {
private int id;
PersonNameChanged() {
}
PersonNameChanged(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "PersonNameChanged [id=" + this.id + "]";
}
}
public static class PersonMoved {
private int id;
PersonMoved() {
}
PersonMoved(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "PersonMoved [id=" + this.id + "]";
}
}
}
Pom:
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.example
so42969130
2.0.0-BUILD-SNAPSHOT
jar
so42969130
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.5.2.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-integration
org.springframework.integration
spring-integration-amqp
org.springframework.integration
spring-integration-java-dsl
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
结果:
2017-03-23 09:56:57.501 INFO 75217 --- [ask-scheduler-2] .s.i.a.AbstractCorrelatingMessageHandler :
Expiring MessageGroup with correlationKey[123]
[PersonNameChanged [id=123], PersonMoved [id=123]]
标签:spring-amqp,rabbitmq,spring,java,spring-integration
来源: https://codeday.me/bug/20191026/1934156.html