springboot+rabbitmq实现多个生产者多个消费者

第一个项目配置

配置文件

  rabbitmq:
    addresses: 127.0.0.1:5672
    username: root
    password: 123456
    listener:
      simple:
        concurrency: 5
        max-concurrency: 10
        acknowledge-mode: manual
        prefetch: 1
        retry:
          initial-interval: 1000
    connection-timeout: 15000
    virtual-host: /
    publisher-confirms: true

监听器

package com.luntek.cloudplatform.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

/**
 * 用于RabbitMQ的消息确认机制
 *
 * @author Administrator
 * @Date 2019/10/12 0012 下午 1:19
 * @Created by Czw
 */
@Slf4j
@Component
public class RabbitmqConfirmListener implements RabbitTemplate.ConfirmCallback {
    
    
    /**
     * 回调函数:confirm确认rabbitmq的ack接收情况
     *
     * @param correlationData 消息信息
     * @param ack             消息是否返回成功
     * @author Czw
     * @date 2019/10/12 0015 下午 8:51
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String s) {
    
    
        log.debug("RabbitMQ回调函数,CorrelationData:{},是否成功:{}", correlationData, ack);
        //获取消息ID
        String messageId = correlationData == null ? "" : correlationData.getId();
        String messageReturn = correlationData == null ? "" : correlationData.toString();
        if (ack) {
    
    

            log.info("RabbitMQ回调函数返回成功,messageId为: {} ,内容为: {} ", messageId, messageReturn);
        } else {
    
    
            log.error("RabbitMQ回调函数返回失败");
        }
    }
}

生产者

package com.luntek.cloudplatform.rabbitmq.producer;

import com.luntek.cloudplatform.listener.RabbitmqConfirmListener;
import com.luntek.cloudplatform.utils.Constants;
import lombok.extern.slf4j.Slf4j;
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 java.util.UUID;

/**
 * 线上赛项组织消息生产者,用于同步数据到云平台项目
 *
 * @author Czw
 * @Date 2019/6/3 0003 上午 11:26
 */
@Slf4j
@Component
public class CompetitionSender {
    
    
    /**
     * 自动注入发送消息的模板
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitmqConfirmListener rabbitmqConfirmListener;


    /**
     * 将需要删除的参赛编号信息发送到队列中
     * 删除数据,fanout模式,rout值失效,根据queue绑定,exchange必须相同
     *
     * @param cards 参赛者参赛编号,删除云平台上的用户数据
     * @author Czw
     * @date 2020/5/21 0021 下午 4:04
     */
    public void sendDeleteCompetitor(String cards) {
    
    
        log.info("***芯云学院RabbitMQ开始发送消息***");
        //correlationData消息唯一id
        CorrelationData correlationData = new CorrelationData();
        String messageId = UUID.randomUUID().toString();
        correlationData.setId(messageId);
        //设置消息确认机制
        rabbitTemplate.setConfirmCallback(rabbitmqConfirmListener);
        //exchange
        rabbitTemplate.convertAndSend(Constants.EXCHANGE_COMPETITOR_DELETE,
                //routingKey 路由key 在rabbitmq中交换机Rout Key对应的值
                "competition.luntek",
                //消息体内容
                cards,
                //correlationData消息唯一id
                correlationData);
        log.info("*****RabbitMQ发送消息完成,消息ID为,{} ,参赛信息为competitions: {} *****", messageId, cards);
    }

}

消费者

package com.luntek.cloudplatform.rabbitmq.consumer;

import com.luntek.cloudplatform.emus.RoleEnum;
import com.luntek.cloudplatform.entity.User;
import com.luntek.cloudplatform.service.MicroService;
import com.luntek.cloudplatform.service.UserService;
import com.luntek.cloudplatform.utils.Constants;
import com.luntek.cloudplatform.utils.FastDFSClientUtil;
import com.luntek.cloudplatform.utils.FastDFSUtil;
import com.luntek.cloudplatform.utils.JsonUtil;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 线上赛项组织消息生产者,用于同步数据到云平台项目
 *
 * @author Czw
 * @Date 2019/6/3 0003 上午 11:28
 */
@Slf4j
@Component
public class CompetitionReceiver {
    
    
    @Autowired
    private UserService userService;
    @Autowired
    private MicroService microService;

    /*
    @RabbitListener 自动在RabbitMQ上面添加交换机、队列,以及设置相关属性;
    @Queue和@Exchange的durable属性都是设置队列为持久化。确保退出或者崩溃
    的时候,将会丢失所有队列和消息(交换机没设置是因为该属性默认true);
    @RabbitHandler 只是标识方法如果有消息过来消费者要消费的时候调用这个方法
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = Constants.QUEUE_COMPETITOR_ADD, durable = "true"),
            exchange = @Exchange(name = Constants.EXCHANGE_COMPETITOR_ADD, type = "topic"),//交换机名称,durable指是否持久化到数据库,type:模式
            key = "competition.*" //路由匹配规则
    ))
    @RabbitHandler
    public void competitionMessage(@Payload String competitions,
                                   @Headers Map<String, Object> headers,
                                   Channel channel) throws Exception {
    
    
        //消费者操作
        log.info("*****CompetitionReceiver:{},开始消费*****", competitions);
        if (competitions != null) {
    
    
            log.info("***CompetitionReceiver开始解析文件内容***");
            List<User> userList = new ArrayList<>();
            List<String> list = JsonUtil.jsonToObject(competitions, List.class);
            for (String s : list) {
    
    
                User user = new User();
                user.setId(UUID.randomUUID().toString());
                user.setLoginTime(0);
                user.setCreateTime(new Date());
                user.setCreateBy("");
                user.setUpdateTime(new Date());
                user.setUpdateBy("");
                user.setVersion(0);
                user.setName("");
                user.setTodayIntegral(0);
                user.setTotalIntegral(0);
                user.setSchoolId(Constants.COMPETITION_SCHOOL);
                User userInfo = userService.getByUserId(s);
                if (userInfo != null) {
    
    
                    log.error("***用户ID {} 已经存在***", s);
                    continue;
                }
                user.setUserId(s);
                user.setIcon("");
                user.setPassword(Constants.ORIGIN_PASSWORD);
                user.setRoleId(RoleEnum.CANDIDATE.getCode());
                userList.add(user);
            }
            if (userList.size() > 0) {
    
    
                //保存数据
                userService.addBatchUser(userList);
            }
            //ACK 手动签收消息,告诉对方消息签收成功,唯一标识ID
            Long deliverTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            channel.basicAck(deliverTag, false);
        }
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = Constants.QUEUE_COMPETITOR_CLOUD_DELETE, durable = "true"),
            //交换机名称,durable指是否持久化到数据库,type:模式 fanout订阅者模式
            exchange = @Exchange(name = Constants.EXCHANGE_COMPETITOR_DELETE, type = "fanout"),
            key = "competition.*" //路由匹配规则
    ))
    /**
     * @RabbitHandler 只是标识方法如果有消息过来消费者要消费的时候调用这个方法
     */
    @RabbitHandler
    @Transactional(rollbackFor = {
    
    Exception.class})
    public void competitionDeleteMessage(@Payload String cards,
                                         @Headers Map<String, Object> headers,
                                         Channel channel) throws Exception {
    
    
        log.info("***云平台中订阅者模式消费者,信息为:{}***", cards);
        //ACK 手动签收消息,告诉对方消息签收成功
        Long deliverTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
        //唯一标识ID
        channel.basicAck(deliverTag, false);
    }
}

第二个项目

配置文件

  rabbitmq:
    addresses: 127.0.0.1:5672
    username: root
    password: 123456
    listener:
      simple:
        concurrency: 5
        max-concurrency: 10
        acknowledge-mode: manual
        prefetch: 1
        retry:
          initial-interval: 1000
    connection-timeout: 15000
    virtual-host: /
    publisher-confirms: true

监听器

package com.luntek.cloudplatform.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

/**
 * 用于RabbitMQ的消息确认机制
 *
 * @author Administrator
 * @Date 2019/10/12 0012 下午 1:19
 * @Created by Czw
 */
@Slf4j
@Component
public class RabbitmqConfirmListener implements RabbitTemplate.ConfirmCallback {
    
    
    /**
     * 回调函数:confirm确认rabbitmq的ack接收情况
     *
     * @param correlationData 消息信息
     * @param ack             消息是否返回成功
     * @author Czw
     * @date 2019/10/12 0015 下午 8:51
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String s) {
    
    
        log.debug("RabbitMQ回调函数,CorrelationData:{},是否成功:{}", correlationData, ack);
        //获取消息ID
        String messageId = correlationData == null ? "" : correlationData.getId();
        String messageReturn = correlationData == null ? "" : correlationData.toString();
        if (ack) {
    
    

            log.info("RabbitMQ回调函数返回成功,messageId为: {} ,内容为: {} ", messageId, messageReturn);
        } else {
    
    
            log.error("RabbitMQ回调函数返回失败");
        }
    }
}

生产者

package com.luntek.certificate.rabbitmq.producer;

import com.luntek.certificate.listener.RabbitmqConfirmListener;
import com.luntek.certificate.utils.StaticParams;
import lombok.extern.slf4j.Slf4j;
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 java.util.UUID;

/**
 * 线上赛项组织消息生产者,用于同步数据到云平台项目
 *
 * @author Czw
 * @Date 2019/6/3 0003 上午 11:26
 */
@Slf4j
@Component
public class CompetitionSender {
    
    
    /**
     * 自动注入发送消息的模板
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitmqConfirmListener rabbitmqConfirmListener;

    /**
     * 同步数据到云平台,topic模式,数据根据rout来消费
     *
     * @param competitions 同步数据到云平台的参赛者数据
     * @author Czw
     * @date 2020/5/21 0021 下午 4:04
     */
    public void send(String competitions) {
    
    
        log.info("*****RabbitMQ开始发送消息*****");
        //correlationData消息唯一id
        CorrelationData correlationData = new CorrelationData();
        String messageId = UUID.randomUUID().toString();
        correlationData.setId(messageId);
        //设置消息确认机制
        rabbitTemplate.setConfirmCallback(rabbitmqConfirmListener);
        //exchange
        rabbitTemplate.convertAndSend(StaticParams.EXCHANGE_COMPETITOR_ADD,
                //routingKey 路由key 在rabbitmq中交换机Rout Key对应的值
                "competition.luntek",
                //消息体内容
                competitions,
                //correlationData消息唯一id
                correlationData);
        log.info("*****RabbitMQ发送消息完成,消息ID为,{} ,参赛信息为competitions: {} *****", messageId, competitions);
    }


    /**
     * 将需要删除的获取参赛编号信息发送到队列中
     * 删除数据,fanout模式,rout值失效,根据queue绑定,exchange必须相同
     *
     * @param cards 参赛者参赛编号,删除云平台上的用户数据
     * @author Czw
     * @date 2020/5/21 0021 下午 4:04
     */
    public void sendDeleteCompetitor(String cards) {
    
    
        log.info("***芯云学院RabbitMQ开始发送消息***");
        //correlationData消息唯一id
        CorrelationData correlationData = new CorrelationData();
        String messageId = UUID.randomUUID().toString();
        correlationData.setId(messageId);
        //设置消息确认机制
        rabbitTemplate.setConfirmCallback(rabbitmqConfirmListener);
        //exchange
        rabbitTemplate.convertAndSend(StaticParams.EXCHANGE_COMPETITOR_DELETE,
                //routingKey 路由key 在rabbitmq中交换机Rout Key对应的值
                "competition.luntek",
                //消息体内容
                cards,
                //correlationData消息唯一id
                correlationData);
        log.info("*****RabbitMQ发送消息完成,消息ID为,{} ,参赛信息为competitions: {} *****", messageId, cards);
    }

}

消费者

package com.luntek.certificate.rabbitmq.consumer;

import com.luntek.certificate.mapper.OnlineCompetitionMapper;
import com.luntek.certificate.utils.JsonUtil;
import com.luntek.certificate.utils.StaticParams;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

/**
 * 线上赛项组织消息生产者,用于同步数据到云平台项目
 *
 * @author Czw
 * @Date 2019/6/3 0003 上午 11:28
 */
@Slf4j
@Component
public class CompetitionReceiver {
    
    

    @Autowired
    private OnlineCompetitionMapper onlineCompetitionMapper;


    /**
     * 将需要删除的用户身份证信息发送到队列中
     * 删除数据,fanout模式,rout值失效,根据queue绑定,exchange必须相同
     *
     * @author Czw
     * @param cards 参赛者身份证,删除云平台上的用户数据
     * @date 2020/5/21 0021 下午 4:13
     * @RabbitHandler 只是标识方法如果有消息过来消费者要消费的时候调用这个方法
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = StaticParams.QUEUE_COMPETITOR_CERTIFICATE_DELETE, durable = "true"),
            //交换机名称,durable指是否持久化到数据库,type:模式 fanout订阅者模式
            exchange = @Exchange(name = StaticParams.EXCHANGE_COMPETITOR_DELETE, type = "fanout"),
            key = "competition.*" //路由匹配规则
    ))
    @RabbitHandler
    public void competitionDeleteMessage(@Payload String cards,
                                         @Headers Map<String, Object> headers,
                                         Channel channel) throws Exception {
    
    
        log.info("***芯云学院中订阅者模式消费者,信息为:{}***", cards);
        //ACK 手动签收消息,告诉对方消息签收成功,唯一标识ID
        Long deliverTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
        channel.basicAck(deliverTag, false);
    }
}

效果

rabbitmq中的exchange和queue
在这里插入图片描述

在第二个项目中调用生产者发送消息,两个项目的消费者同时收到消息能进行消费
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42910468/article/details/106289296