RabbitMQ多线程消费

274 阅读2分钟

RabbitMQ实现并发多线程消费

1.springBoot集成RabbitMQ

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2.YML文件配置

server:
  port: 7890

spring:
  rabbitmq:
    host: 172.15.33.52
    port: 5672
    username: root
    password: 123456

实例

1.文件配置实现

cloud:
 stream:
   default-binder: cogoMq
   rabbit: #多集群的情况下仍然需要配置在该目录下
     bindings:
       fundEnterResult-in-0:
         fundEnterResult:
           acknowledgeMode: manual
         consumer:
           maxConcurrency: 10
       tradeRiskAuditResult-in-0:
         tradeRiskAuditResult:
           acknowledgeMode: manual
         consumer:
           maxConcurrency: 10
       vaStatusChange-out-0:
         producer:
           bindQueue: false
           exchangeType: direct
           declareExchange: false
           exchangeAutoDelete: false
           queueNameGroupOnly: true
   bindings:
     fundEnterResult-in-0:
       destination: dfsfsfTest #交换器名称
       group: COGO_NTER_QUEUE #队列名称
       binder: cogoMq #绑定器
       consumer:
         concurrency: 5
     tradeRiskAuditResult-in-0:
       destination: 454545Test #交换器名称
       group: TASCB_COLLECT #队列名称
       binder: cogoMq #绑定器
       consumer:
         concurrency: 5
     vaStatusChange-out-0:
       destination: 5665656test #交换器名称
       group: COGO_RECOVER #队列名称
       binder: cogoMq #绑定器
   binders:
     cogoMq:
       type: rabbit
       environment: #可用于自定义绑定器环境的一组属性,设置这个属性后,可以实现Binder组件和应用组件的隔离 默认值:空
         spring:
           rabbitmq:
             host: *****
             port: *****
             username: ****
             password: ****
             publisher-confirm-type: correlated
             publisher-returns: true
             virtual-host: /
             ssl:
               enabled: false
 function:
   definition: fundEnterResult;tradeRiskAuditResult

结果展示

企业微信截图_16898468729538.png

2.工厂配置实现

package com.cogo.collect.config;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *
 **/
@Configuration
public class RabbitMQConfig {

    //消费者最小并发数量
    public static final int DEFAULT_CONCURRENT_MIN = 6;
    //消费者最大并发数量
    public static final int DEFAULT_CONCURRENT_MAX = 11;
    //预取次数
    public static final int PREFETCH = 3;

    public static final String CUSTOM_CONTAINER_FACTORY = "customContainerFactory";
    public static final String FUND_ENTER_RESULT_QUEUE = "COGO_TRADE_FUND_ENTER_QUEUE11221";

    @Bean(CUSTOM_CONTAINER_FACTORY)
    public SimpleRabbitListenerContainerFactory containerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        //要创建的消费者的最小数量。
        factory.setConcurrentConsumers(DEFAULT_CONCURRENT_MIN);
        //最大的消费者数量。
        factory.setMaxConcurrentConsumers(DEFAULT_CONCURRENT_MAX);
        //预取次数
        factory.setPrefetchCount(PREFETCH);
        //手动ACK
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        configurer.configure(factory, connectionFactory);
        return factory;
    }


}
package com.cogo.collect.stream.customer;

import com.cogo.collect.config.RabbitMQConfig;
import com.cogo.collect.enums.CoGoCollectExceptionEnum;
import com.cogo.collect.remote.request.FundEnterRequest;
import com.cogo.collect.service.order.AccountIncomeBusinessV1Service;
import com.cogo.common.util.UUIDUtils;
import com.cogo.metric.MetricMessagePusher;
import com.suixingpay.ace.common.json.JsonUtil;
import com.suixingpay.ace.data.api.Response;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.function.Consumer;

@Slf4j
@Configuration
public class FundEnterResultConsumer {

    @Resource
    private AccountIncomeBusinessV1Service accountIncomeBusinessV1Service;

    /**
     * 到账/入账接收
     *
     * @author zhaozj
     * @project cogo-collect
     * @date 2023-03-22
     * @desc 到账/入账
     */
    @Bean
    @RabbitListener(queues = {RabbitMQConfig.FUND_ENTER_RESULT_QUEUE },
            containerFactory = RabbitMQConfig.CUSTOM_CONTAINER_FACTORY)
    public Consumer<String> fundEnterResult() {
        log.info("初始化-队列: fundEnterResult 到账/入账通知结果");
        return message -> {
            Response response = null;
            try {
                MDC.put("tradenum", UUIDUtils.getUUID());
                log.info("接收fundEnterResult 队列 结果: {}", message);
                FundEnterRequest request = JsonUtil.jsonToObject(message, FundEnterRequest.class);
                log.info("转换request对象之后的结果:{}", request);
                response = accountIncomeBusinessV1Service.fundEnter(request);
            } catch (Exception e) {
                log.error("新接收fundEnterResult 队列 发生异常{}, 消息:{}", e.getMessage(), message);
                response = Response.failOf("到账/入账处理失败");
            }
            if (!response.isSuccess()) {
                MetricMessagePusher.pushMetric(CoGoCollectExceptionEnum.ENTER_INCOME_ERROR.getCode(), "资金入账处理异常", String.format("资金入账处理异常通知结果失败原因:%s,入账通知请求参数:%s", response.getMessage(), message));
            }
            log.info("到账/入账处理响应结果:{}", response);
        };
    }
}

遇到问题

org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$DeclarationException: Failed to declare queue(s):[COGO_TRADE_FUND_ENTER_QUEUE11221] 
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'COGO_TRADE_FUND_ENTER_QUEUE11221-111' in vhost '/', class-id=50, method-id=10)

解决问题

手动创建队列 企业微信截图_16898453526286.png 结果展示

企业微信截图_16898456492701.png