RabbitMQ 保障 100% 消息投递方案

RabbitMQ 保障 100% 消息投递方案

设计方案一

RabbitMQ 保障 100% 消息投递方案_第1张图片

消息重复投递 ,需要消费者做幂等处理。

定义消息状态,0 表示消息发送中,1 表示消息发送成功,2 表示消息发送失败。

Step 1:将业务数据和消息写入到数据库中,

Step 2:生产者将消息发送到 RabbitMQ Broker 中,

Step 3:生产者监听 RabbitMQ Broker 的应答,

Step 4:如果应答信息,消息发送成功,更新消息库消息的状态为成功 1;如果无应答信息,则消息发送失败;

Step :5:用定时任务重新扫描消息库中消息状态为 0 的消息,进行消息重新发送;

Step 6:设置消息重试次数,使用定时任务尝试发送状态为 0 的消息,如果还是发送都不成功,消息状态更改为失败,进行人工补偿消息。

Java 实现

common 包下实体类

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;
}

pom.xml


<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>

application.yml

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);
    }
}

你可能感兴趣的:(JMS)