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
结果展示
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)
解决问题
手动创建队列
结果展示