美文网首页
乐优商城学习笔记二十一-RabbitMQ项目改造

乐优商城学习笔记二十一-RabbitMQ项目改造

作者: smallmartial | 来源:发表于2019-04-22 16:31 被阅读0次

    title: 乐优商城学习笔记二十一-RabbitMQ项目改造
    date: 2019-04-22 16:22:07
    tags:
    - 乐优商城
    - java
    - RabbitMQ
    categories:
    - 乐优商城


    3.项目改造

    接下来,我们就改造项目,实现搜索服务、商品静态页的数据同步。

    3.1.思路分析

    发送方:商品微服务

    • 什么时候发?

      当商品服务对商品进行写操作:增、删、改的时候,需要发送一条消息,通知其它服务。

    • 发送什么内容?

      对商品的增删改时其它服务可能需要新的商品数据,但是如果消息内容中包含全部商品信息,数据量太大,而且并不是每个服务都需要全部的信息。因此我们只发送商品id,其它服务可以根据id查询自己需要的信息。

    接收方:搜索微服务、静态页微服务

    • 接收消息后如何处理?
      • 搜索微服务:
        • 增/改:添加新的数据到索引库
        • 删:删除索引库数据
      • 静态页微服务:
        • 增:创建新的静态页
        • 删:删除原来的静态页
        • 改:创建新的静态页并删除原来的

    3.2.发送消息

    我们先在商品微服务ly-item-service中实现发送消息。

    3.2.1.引入依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    

    3.2.2.配置文件

    我们在application.yml中添加一些有关RabbitMQ的配置:

    spring:
      rabbitmq:
        host: 192.168.56.101
        username: leyou
        password: leyou
        virtual-host: /leyou
        template:
          retry:
            enabled: true
            initial-interval: 10000ms
            max-interval: 300000ms
            multiplier: 2
          exchange: ly.item.exchange
        publisher-confirms: true
    
    • template:有关AmqpTemplate的配置
      • retry:失败重试
        • enabled:开启失败重试
        • initial-interval:第一次重试的间隔时长
        • max-interval:最长重试间隔,超过这个间隔将不再重试
        • multiplier:下次重试间隔的倍数,此处是2即下次重试间隔是上次的2倍
      • exchange:缺省的交换机名称,此处配置后,发送消息如果不指定交换机就会使用这个
    • publisher-confirms:生产者确认机制,确保消息会正确发送,如果发送失败会有错误回执,从而触发重试

    3.2.3.改造GoodsService

    封装一个发送消息到mq的方法:

    private void sendMessage(Long id, String type){
        // 发送消息
        try {
            this.amqpTemplate.convertAndSend("item." + type, id);
        } catch (Exception e) {
            logger.error("{}商品消息发送异常,商品id:{}", type, id, e);
        }
    }
    
    • 这里没有指定交换机,因此默认发送到了配置中的:ly.item.exchange

    注意:这里要把所有异常都try起来,不能让消息的发送影响到正常的业务逻辑

    然后在新增的时候调用:

    1527156169187

    修改的时候调用:

    [图片上传失败...(image-1d3f1a-1555921884003)]

    3.3.搜索服务接收消息

    搜索服务接收到消息后要做的事情:

    • 增:添加新的数据到索引库
    • 删:删除索引库数据
    • 改:修改索引库数据

    因为索引库的新增和修改方法是合二为一的,因此我们可以将这两类消息一同处理,删除另外处理。

    3.3.1.引入依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    

    3.3.2.添加配置

    spring:
      rabbitmq:
        host: 192.168.56.101
        username: leyou
        password: leyou
        virtual-host: /leyou
    

    这里只是接收消息而不发送,所以不用配置template相关内容。

    3.3.3.编写监听器

    [图片上传失败...(image-6294f-1555921884003)]

    代码:

    @Component
    public class GoodsListener {
    
        @Autowired
        private SearchService searchService;
    
        /**
         * 处理insert和update的消息
         *
         * @param id
         * @throws Exception
         */
        @RabbitListener(bindings = @QueueBinding(
                value = @Queue(value = "ly.create.index.queue", durable = "true"),
                exchange = @Exchange(
                        value = "ly.item.exchange",
                        ignoreDeclarationExceptions = "true",
                        type = ExchangeTypes.TOPIC),
                key = {"item.insert", "item.update"}))
        public void listenCreate(Long id) throws Exception {
            if (id == null) {
                return;
            }
            // 创建或更新索引
            this.searchService.createIndex(id);
        }
    
        /**
         * 处理delete的消息
         *
         * @param id
         */
        @RabbitListener(bindings = @QueueBinding(
                value = @Queue(value = "ly.delete.index.queue", durable = "true"),
                exchange = @Exchange(
                        value = "ly.item.exchange",
                        ignoreDeclarationExceptions = "true",
                        type = ExchangeTypes.TOPIC),
                key = "item.delete"))
        public void listenDelete(Long id) {
            if (id == null) {
                return;
            }
            // 删除索引
            this.searchService.deleteIndex(id);
        }
    }
    

    3.3.4.编写创建和删除索引方法

    这里因为要创建和删除索引,我们需要在SearchService中拓展两个方法,创建和删除索引:

    
    public void createIndex(Long id) {
            //查询spu
            Spu spu = goodClient.querySpuById(id);
            //构建goods
            Goods goods = bulidGoods(spu);
            //存入索引库
            repository.save(goods);
    
        }
    
    public void deleteIndex(Long id) {
        this.goodsRepository.deleteById(id);
    }
    

    创建索引的方法可以从之前导入数据的测试类中拷贝和改造。

    3.4.静态页服务接收消息

    商品静态页服务接收到消息后的处理:

    • 增:创建新的静态页
    • 删:删除原来的静态页
    • 改:创建新的静态页并删除原来的

    不过,我们编写的创建静态页的方法也具备覆盖以前页面的功能,因此:增和改的消息可以放在一个方法中处理,删除消息放在另一个方法处理。

    3.4.1.引入依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    

    3.4.2.添加配置

    spring:
      rabbitmq:
        host: 192.168.56.101
        username: leyou
        password: leyou
        virtual-host: /leyou
    

    这里只是接收消息而不发送,所以不用配置template相关内容。

    3.4.3.编写监听器

    [图片上传失败...(image-796952-1555921884003)]

    代码:

    @Component
    public class GoodsListener {
    
        @Autowired
        private FileService fileService;
    
        @RabbitListener(bindings = @QueueBinding(
                value = @Queue(value = "ly.create.page.queue", durable = "true"),
                exchange = @Exchange(
                        value = "ly.item.exchange", 
                        ignoreDeclarationExceptions = "true", 
                        type = ExchangeTypes.TOPIC),
                key = {"item.insert", "item.update"}))
        public void listenCreate(Long id) throws Exception {
            if (id == null) {
                return;
            }
            // 创建页面
            fileService.createHtml(id);
        }
    
        @RabbitListener(bindings = @QueueBinding(
                value = @Queue(value = "ly.delete.page.queue", durable = "true"),
                exchange = @Exchange(
                        value = "ly.item.exchange", 
                        ignoreDeclarationExceptions = "true", 
                        type = ExchangeTypes.TOPIC),
                key = "item.delete"))
        public void listenDelete(Long id) {
            if (id == null) {
                return;
            }
            // 创建页面
            fileService.deleteHtml(id);
        }
    }
    

    3.4.4.添加删除页面方法

    public void deleteHtml(Long id) {
        File file = new File(this.destPath, id + ".html");
        file.deleteOnExit();
    }
    

    3.5.测试

    查看RabbitMQ控制台

    重新启动项目,并且登录RabbitMQ管理界面:http://192.168.56.101:15672

    可以看到,交换机已经创建出来了:

    [图片上传失败...(image-2c65fa-1555921884003)]

    队列也已经创建完毕:

    [图片上传失败...(image-7985d4-1555921884003)]

    并且队列都已经绑定到交换机:

    [图片上传失败...(image-44cd34-1555921884003)]

    查看数据

    我们搜索下手机:

    [图片上传失败...(image-9a3c4d-1555921884003)]

    商品详情页:

    [图片上传失败...(image-9c6350-1555921884003)]

    修改商品

    然后在管理后台修改商品:

    我们修改以下内容:

    标题改成6.1

    [图片上传失败...(image-9f54b1-1555921884003)]

    商品详情加点文字:

    [图片上传失败...(image-d42ddd-1555921884003)]

    价格改为3999

    [图片上传失败...(image-80f0a5-1555921884003)]

    再次查看数据

    [图片上传失败...(image-53fdca-1555921884003)]

    [图片上传失败...(image-6e1bc9-1555921884003)]

    [图片上传失败...(image-7cdc94-1555921884003)]

    相关文章

      网友评论

          本文标题:乐优商城学习笔记二十一-RabbitMQ项目改造

          本文链接:https://www.haomeiwen.com/subject/tfhugqtx.html