消息重复投递 ,需要消费者做幂等处理。
定义消息状态,0 表示消息发送中,1 表示消息发送成功,2 表示消息发送失败。
Step 1:将业务数据和消息写入到数据库中,
Step 2:生产者将消息发送到 RabbitMQ Broker 中,
Step 3:生产者监听 RabbitMQ Broker 的应答,
Step 4:如果应答信息,消息发送成功,更新消息库消息的状态为成功 1;如果无应答信息,则消息发送失败;
Step :5:用定时任务重新扫描消息库中消息状态为 0 的消息,进行消息重新发送;
Step 6:设置消息重试次数,使用定时任务尝试发送状态为 0 的消息,如果还是发送都不成功,消息状态更改为失败,进行人工补偿消息。
package top.simba1949.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author SIMBA1949
* @date 2019/6/25 18:57
*/
@Data
public class Order implements Serializable {
private static final long serialVersionUID = 4541482610178181251L;
private String id;
private String name;
private String messageId;
}
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>top.simba1949groupId>
<artifactId>reliable-publisherartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.4.RELEASEversion>
parent>
<properties>
<lombok.version>1.18.6lombok.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
<dependency>
<groupId>top.simba1949groupId>
<artifactId>commonartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
<build>
<defaultGoal>installdefaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.0version>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<version>3.1.0version>
<configuration>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
configuration>
plugin>
plugins>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.xmlinclude>
<include>**/*.propertiesinclude>
<include>**/*.ymlinclude>
includes>
resource>
resources>
build>
project>
server:
port: 8081
servlet:
context-path: /
spring:
application:
name: spring-boot-integrated-rabbitmq-sbs-amqp
rabbitmq:
addresses: 192.168.232.128:5672
username: rabbitmq
password: rabbitmq
virtual-host: /
# 连接超时时间
connection-timeout: 15000
# 消息发送到交换机确认机制,是否返回回调
publisher-returns: true
# 消息发送到交换机确认机制,是否确认回调
publisher-confirms: true
package top.simba1949.publisher;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.simba1949.entity.Order;
import java.util.UUID;
/**
* @author SIMBA1949
* @date 2019/6/26 13:50
*/
@Component
public class OrderPublisher {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* rabbitmq 回调机制
*/
final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback(){
@Override
public void confirm(CorrelationData correlationData, boolean ack, String s) {
System.out.println("correlationData : " + correlationData);
if (ack){
// 如果confirm返回成功,则进行更新
System.out.println("应答成功");
} else {
// 失败则进行具体的后续操作,重新或者补偿等手段
System.out.println("应答失败");
}
}
};
public void send(Order order){
rabbitTemplate.setConfirmCallback(confirmCallback);
// 交换机
String exchange = "order-exchange";
// 路由规则
String routingKey = "order.test";
CorrelationData correlationData = new CorrelationData();
correlationData.setId(UUID.randomUUID().toString());
// 第一个参数:生产者要发送的交换机
// 第二个参数:消息路由规则
// 第三个参数:消息体
// 第四个参数:消息唯一id
rabbitTemplate.convertAndSend(exchange,routingKey, order, correlationData);
}
}
package top.simba1949.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.simba1949.entity.Order;
import top.simba1949.publisher.OrderPublisher;
import java.util.UUID;
/**
* @author SIMBA1949
* @date 2019/6/26 14:13
*/
@RequestMapping("order")
@RestController
public class OrderController {
@Autowired
private OrderPublisher orderPublisher;
@GetMapping("")
public String send(){
Order order = new Order();
order.setId(UUID.randomUUID().toString());
order.setName("nameName");
order.setMessageId(System.currentTimeMillis() + "$" + UUID.randomUUID().toString());
orderPublisher.send(order);
return "SUCCESS";
}
}
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author SIMBA1949
* @date 2019/6/26 13:00
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}