在前面订单服务调用商品服务时候,我们采用的是同步的方式。订单服务调用商品服务,商品服务库存进行操作。如果订单服务这里需要同时调用支付服务、商品服务多个服务时,等待各个服务响应完,整个订单请求才算执行完毕,这对程序使用体验大打折扣。
而异步时,客户端请求不会阻塞进程,服务端的响应可以是非即时的。
异步常见形态
- 通知 -------------单向请求,单当面的发送请求。
- 请求/异步响应---- 客户端发送请求到客户端,客户端非即时响应
- 消息------------ 消息的生产与消费,这里我们已MQ为主
MQ应用场景
1、异步处理
2、流量削峰
3、日志处理
4、应用解耦
MQ的基础使用
1、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、添加配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3、创建消息接收方
使用注解@RabbitListener
监听队列情况
/**
* 接收方
*/
@Component
@Slf4j
public class ReceiveMessage {
@RabbitListener(queues = "myqueue")
public void receive(String messge) {
log.info("message={}",messge);
}
}
4、消息发送测试
/**
* 发送mq消息测试
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ReceiveMessageTest {
@Autowired
private AmqpTemplate amqpTemplate;
@Test
public void send() throws Exception {
amqpTemplate.convertAndSend("myqueue","now :" + new Date());
}
}
5、在web页面手动添加一个myqueue队列,进行测试。
在上面基础操作中,队列还需要我们在RabbitMq中手动床架,这肯定是不符合项目中自动创建需要的。
- 使用下面注解方式可以自动创建队列
@RabbitListener(queuesToDeclare = @Queue("myQueue"))
- 自动创建队列,并将Exchange和Queue进行绑定
@RabbitListener(bindings = @QueueBinding(
value = @Queue("myQueue"),
exchange = @Exchange("myExchange")
))
如果在一条订单中有数码商品服务和水果商品服务进行交互,这个时候需要对订单交换机(Exchange)进行分组,来调用不同的队列。
简单案例:
1、模拟数码服务和水果服务
/**
* 数码供应商服务 接收消息
* @param messge
*/
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange("myOrder"),
key = "computer",
value = @Queue("computerOrder")
))
public void processComputer(String messge) {
log.info("computer MqReceive: {}",messge);
}
/**
* 水果供应商服务 接收消息
* @param messge
*/
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange("myOrder"),
key = "fruit",
value = @Queue("fruitOrder")
))
public void fruitComputer(String messge) {
log.info("computer MqReceive: {}",messge);
}
2、模拟订单消息发送方
这里**converAndSend()**方法根据exchang交换机和分组key,即可找到接收消息的队列
/**
* 订单发送方
* @throws Exception
*/
@Test
public void sendOrder() throws Exception {
amqpTemplate.convertAndSend("myOrder","computer","now :" + new Date());
}