目录
2.2 利用SpringAMQP实现HelloWorld中的基础消息队列功能
2.4 发布( Publish )、订阅( Subscribe )
1. 同步通讯和异步通讯
手机通话属于同步通信,微信聊天属于异步通信
1.1 同步通信与异步通信区别:
1.同步通信要求接收端时钟频率和发送端时钟频率一致,发送端发送连续的比特流;异步通信时不要求接收端时钟和发送端时钟同步,发送端发送完一个字节后,可经过任意长的时间间隔再发送下一个字节。
2.同步通信效率高;异步通信效率较低。
3.同步通信较复杂,双方时钟的允许误差较小;异步通信简单,双方时钟可允许一定误差。
4.同步通信可用于点对多点;异步通信只适用于点对点。
1.2 同步调用的问题
微服务间基于Feign的调用就属于同步方式,存在一些问题。
同步调用的时间之和为调用给微服务之和及自身时间之和(耗时长,用户体验差)
1.2.1 同步调用的缺点
1.2.2 总结
1.3 异步调用方案
1.3.1 异步调用常见实现就是事件驱动模式
1.3.2 事件驱动优势
1.3.3 总结
1.4 快速入门MQ
MQ (MessageQueue),中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。
1.4.1 RabbitMQ概述
RabbitMQ的结构和概念
1.4.2 总结
1.4.3 常见消息模型
1.4.4 HelloWorld案例
官方的HelloWorld是基于最基础的消息队列模型来实现的,只包括三个角色:
1.4.5 总结
2. SpringAMQP
2.1 什么是SpringAMQP
SpringAmqp的官方地址:Spring AMQP
- Basic Queue 简单队列模型
- Work Queue 工作队列模型
- 发布、订阅模型-Fanout
- 发布、订阅模型-Direct
- 发布、订阅模型-Topic
- 消息转换器
2.2 利用SpringAMQP实现HelloWorld中的基础消息队列功能
流程如下:
- 在父工程中引入spring-amqp的依赖
- 在publisher服务中利用RabbitTemplate发送消息到simple.queue这个队列
- 在consumer服务中编写消费逻辑,绑定simple.queue这个队列
步骤1:引入AMQP依赖
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
步骤2:在publisher中编写测试方法,向simple.queue发送消息
1.在publisher服务中编写application.yml,添加mq连接信息:
spring:
rabbitmq:
host: 192.168.150.101 # 主机名
port: 5672 # 端口
virtual-host: / # 虚拟主机
username: itcast # 用户名
password: 123321 # 密码
2.在publisher服务中新建一个测试类,编写测试方法:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testSimpleQueue() {
String queueName = "simple.queue";
String message = "hello, spring amqp!";
rabbitTemplate.convertAndSend(queueName, message);
}
}
步骤3:在consumer中编写消费逻辑,监听simple.queue
2.2.1 总结
2.3 Work Queue 工作队列
Work queue,工作队列,可以提高消息处理速度,避免队列消息堆积
消费者代码
2.3.1 总结
2.4 发布( Publish )、订阅( Subscribe )
发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入了exchange(交换机)。
注意:exchange负责消息路由,而不是存储,路由失败则消息丢失
Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue
2.4.1发布订阅-Fanout Exchange
利用SpringAMQP演示FanoutExchange的使用
实现思路如下:
- 在consumer服务中,利用代码声明队列、交换机,并将两者绑定
- 在consumer服务中,编写两个消费者方法,分别监听fanout.queue1和fanout.queue2
- 在publisher中编写测试方法,向itcast.fanout发送消息
步骤1:在consumer服务声明Exchange、Queue、Binding
SpringAMQP提供了声明交换机、队列、绑定关系的API,例如:
在consumer服务常见一个类,添加@Configuration注解,并声明FanoutExchange、Queue和绑定关系对象Binding,代码如下:
@Configuration
public class FanoutConfig {
// 声明FanoutExchange交换机
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("itcast.fanout");
}
// 声明第1个队列
@Bean
public Queue fanoutQueue1(){
return new Queue("fanout.queue1");
}
// 绑 定队列1和交换机
@Bean
public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
}
// ... 略, 以相同方式声明第2个队列,并完成绑定
}
步骤2:在consumer服务声明两个消费者
在consumer服务的SpringRabbitListener类中,添加两个方法,分别监听fanout.queue1和fanout.queue2:
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {
System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}
@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String msg) {
System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}
步骤3:在publisher服务发送消息到FanoutExchange
2.4.2 总结
2.5 发布订阅-DirectExchange
Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。
- 每一个Queue都与Exchange设置一个BindingKey
- 发布者发送消息时,指定消息的RoutingKey
- Exchange将消息路由到BindingKey与消息RoutingKey一致的队列
2.5.1 总结
2.6 发布订阅-TopicExchange