RabbitMQ使用例子
02、数据同步:思路分析及常量准备
我们已经完成了对MQ的基本学习和认识。接下来,我们就改造项目,实现搜索服务、商品静态页的数据同步。
1)思路分析
发送方:商品微服务
-
什么时候发?
当商品服务对商品进行新增和上下架的时候,需要发送一条消息,通知其它服务。
-
发送什么内容?
对商品的增删改时其它服务可能需要新的商品数据,但是如果消息内容中包含全部商品信息,数据量太大,而且并不是每个服务都需要全部的信息。因此我们只发送商品id,其它服务可以根据id查询自己需要的信息。
接收方:搜索微服务、静态页微服务
-
接收消息后如何处理?
-
搜索微服务:
-
上架:添加新的数据到索引库
-
下架:删除索引库数据
-
-
静态页微服务:
-
上架:创建新的静态页
-
下架:删除原来的静态页
-
-
2)常量准备
在ly-common中编写一个常量类,记录将来会用到的Exchange名称、Queue名称、routing_key名称
package com.leyou.common.constants;
/**
* @author 黑马程序员
*/
public abstract class MQConstants {
public static final class Exchange {
/**
* 商品服务交换机名称
*/
public static final String ITEM_EXCHANGE_NAME = "ly.item.exchange";
}
public static final class RoutingKey {
/**
* 商品上架的routing-key
*/
public static final String ITEM_UP_KEY = "item.up";
/**
* 商品下架的routing-key
*/
public static final String ITEM_DOWN_KEY = "item.down";
}
public static final class Queue{
/**
* 搜索服务,商品上架的队列
*/
public static final String SEARCH_ITEM_UP = "search.item.up.queue";
/**
* 搜索服务,商品下架的队列
*/
public static final String SEARCH_ITEM_DOWN = "search.item.down.queue";
/**
* 商品详情服务,商品上架的队列
*/
public static final String PAGE_ITEM_UP = "page.item.up.queue";
/**
* 商品详情服务,商品下架的队列
*/
public static final String PAGE_ITEM_DOWN = "page.item.down.queue";
}
}
这些常量我们用一个图来展示用在什么地方:
03、数据同步:商品微服务发送消息
我们先在商品微服务ly-item中实现发送消息。
1)引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2)配置文件
我们在application.yml中添加一些有关RabbitMQ的配置:
spring
-
template:有关
AmqpTemplate的配置-
retry:失败重试
-
enabled:开启失败重试
-
initial-interval:第一次重试的间隔时长
-
max-interval:最长重试间隔,超过这个间隔将不再重试
-
multiplier:下次重试间隔的倍数,此处是2即下次重试间隔是上次的2倍
-
-
exchange:缺省的交换机名称,此处配置后,发送消息如果不指定交换机就会使用这个
-
-
publisher-confirms:生产者确认机制,确保消息会正确发送,如果发送失败会有错误回执,从而触发重试
3)Json消息序列化方式(选做)
需要注意的是,默认情况下,AMQP会使用JDK的序列化方式进行处理,传输数据比较大,效率太低。我们可以自定义消息转换器,使用JSON来处理:
package com.leyou.item.config;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置json消息转换
*/
4)改造GoodsService
改造GoodsService中的商品上下架功能,发送消息,注意用静态导入方式,导入在ly-common中定义的常量:
public void updateSaleable(Long id, Boolean saleable) {
try {
Spu spu = new Spu();
spu.setId(id);
spu.setSaleable(saleable);
spuMapper.updateById(spu);//注意:updateById可以自动判断NULL不更新
//发送消息给MQ
String routingKey = saleable? MQConstants.RoutingKey.ITEM_UP_KEY:MQConstants.RoutingKey.ITEM_DOWN_KEY;
amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME,routingKey,id);
} catch (Exception e) {
e.printStackTrace();
throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
}
}
注意:此刻不能启动项目测试,因为rabbitMQ中还没有交换机和队列。
04、数据同步:搜索微服务接收消息
搜索服务接收到消息后要做的事情:
-
上架:添加新的数据到索引库
-
下架:删除索引库数据
我们需要两个不同队列,监听不同类型消息。
1)引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2)添加配置
spring
这里只是接收消息而不发送,所以不用配置template相关内容。
3)Json消息序列化配置
不过,不要忘了消息转换器(如果生产者没有加消息转换器,那么消费者也不要加):
/**
* @author 黑马程序员
*/
4)编写监听器
代码:
package com.leyou.search.mq;
import com.leyou.common.constants.MQConstants;
import com.leyou.search.service.SearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 商品上下架监听
*/
