1. 核心概念图示
- 基础架构
2. 基础概念
- Barista接口:用来定义通道类型和通道名称,通道名称是作为配置用,通道类型则决定了app会使用这个通道进行发送消息还是从中接收消息。包含了:@Output:输出注解,用于定义发送消息的接口;@Input:输入注解,用于定义消息的消费者接口;@StreamListener:用于定义监听方法的注解。缺点: 无法实现可靠性消息投递,会存在少量的消息丢失的问题。
3. 配置RabbitMQ
-
选择合适的Spring cloud和对应的Spring Boot版本。
-
POM文件配置
<!-- Spring Boot版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<!-- Spring Cloud版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Spring Cloud Stream和RabbitMQ -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>1.3.4.RELEASE</version>
</dependency>
4. 生产端配置
- application.yml文件配置
spring:
application:
name: Stream-rabbitMq-producer
cloud:
stream:
binders:
output-channel:
destination: exchange-1 #交换机
group: queue-1 #队列
binder: rabbit_cluster #集群环境
rabbit_cluster: # 集群配置<这个属性对应上方的binder>
type: rabbit # 指定MQ类型, 也可以换成RocketMQ等
environment:
spring:
rabbitmq:
address: 192.168.11.32:5672
username: guest
password: guest
virtual-host: /
server:
port: 9000
servlet: context-path: /producer
- 代码编写发送端
// 定义发送channel.
public interface BaristaOutput {
String OUTPUT_CHANNEL = "output_channel";
@Output(value = BaristaOutput.OUTPUT_CHANNEL)
MessageChannel logOutPut();
}
@EnableBinding(BaristaOutput.class) // 绑定消息发送的通道配置
@Service
public class RabbitMqSender {
@Autowired
private BaristaOutput baristaOutput;
public String sendMessage(Object message, Map<String, Object> properties) throws Exception { try {
MessageHeaders headers = new MessageHeaders(properties);
Message<Object> sendMessage = MessageBuilder.createMessage(message, headers);
boolean sendStatus = baristaOutput.logOutPut().send(sendMessage);
System.out.println("=========sending==========");
System.out.println("发送数据:" + message + ", status: " + sendStatus);
} catch (Exception e) { System.out.println("==========error==========");
throw new RuntimeException(e);
}
return null;
}
}
5. 生产端配置
- application.yml文件配置
spring:
application:
name: Stream-rabbitMq-cusumer
cloud:
stream:
binders:
input_channel:
destination: exchange-1 #交换机 应和producer的exchange一致
group: queue-1 #队列 应和producer的exchange一致
binder: rabbitmq-cluster #集群环境
consumer: # 消费端配置
concurrency: 1 # 默认监听数
requeue-rejected: false # 是否重回队列
acknowledge-mode: MANUAL # 手工签收
recovery-interval: 3000 # 3s重连
durable-subscription: true #持久化订阅
max-concurrency: 5 # 最大监听数
rabbitmq-cluster: # 集群配置<这个属性对应上方的binder>
type: rabbit # 指定MQ类型, 也可以换成RocketMQ等
environment:
spring:
rabbitmq:
address: 192.168.11.32:5672
username: guest
password: guest
virtual-host: /
server:
port: 9001
servlet: context-path: /cusumer
- 代码编写消费端
// 消费端channel
public interface BaristaInput {
String INPUT_CHANNEL = "input_channel";
@Input(value = BaristaInput.INPUT_CHANNEL)
SubscribableChannel logInPut();
}
@EnableBinding(BaristaInput.class) // 绑定消息接收的通道配置
@Service
public class RabbitMqReceiver {
@StreamListener(value = BaristaInput.INPUT_CHANNEL)
public void receiverMessage(Message message) throws IOException {
// 获取channel, 需要使用channel进行ACK
Channel channel = (Channel) message.getHeaders().get(AmqpHeaders.CHANNEL);
// 获取DELIVERY_TAG
Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
System.out.println("收到的消息: " + message);
System.out.println("===========");
channel.basicAck(deliveryTag, false);
}
}