文章目录

  • 0.学习目标
  • 1.RabbitMQ
    • 1.1.搜索与商品服务的问题
    • 1.2.消息队列(MQ)
      • 1.2.1.什么是消息队列
      • 1.2.2.AMQP和JMS
      • 1.2.3.常见MQ产品
      • 1.2.4.RabbitMQ
    • 1.3.下载和安装
  • 2.五种消息模型
  • 3.项目改造
    • 3.1.思路分析
    • 3.2.商品服务发送消息
      • 3.2.1.引入依赖
      • 3.2.2.配置文件
      • 3.2.3.改造GoodsService
    • 3.3.搜索服务接收消息
      • 3.3.1.引入依赖
      • 3.3.2.添加配置
      • 3.3.3.编写监听器
      • 3.3.4.编写创建和删除索引方法
    • 3.4.静态页服务接收消息
      • 3.4.1.引入依赖
      • 3.4.2.添加配置
      • 3.4.3.编写监听器
      • 3.4.4.添加删除页面方法
    • 3.5.测试
      • 3.5.1.查看RabbitMQ控制台
      • 3.5.2.修改数据试一试

0.学习目标

  • 了解常见的MQ产品
  • 了解RabbitMQ的5种消息模型
  • 利用MQ实现搜索和静态页的数据同步

源码及笔记:
链接:https://pan.baidu.com/s/1REHmVFclFI9_pu1ESB_sZw
提取码:voyc

1.RabbitMQ

1.1.搜索与商品服务的问题

目前我们已经完成了商品详情和搜索系统的开发。我们思考一下,是否存在问题?

  • 商品的原始数据保存在数据库中,增删改查都在数据库中完成。
  • 搜索服务数据来源是索引库,如果数据库商品发生变化,索引库数据不能及时更新。
  • 商品详情做了页面静态化,静态页面数据也不会随着数据库商品发生变化。

如果我们在后台修改了商品的价格,搜索页面和商品详情页显示的依然是旧的价格,这样显然不对。该如何解决?

这里有两种解决方案:

  • 方案1:每当后台对商品做增删改操作,同时要修改索引库数据及静态页面
  • 方案2:搜索服务和商品页面服务对外提供操作接口,后台在商品增删改后,调用接口

以上两种方式都有同一个严重问题:就是代码耦合,后台服务中需要嵌入搜索和商品页面服务,违背了微服务的独立原则。

所以,我们会通过另外一种方式来解决这个问题:消息队列

1.2.消息队列(MQ)

1.2.1.什么是消息队列

消息队列,即MQ,Message Queue。

消息队列是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了生产者和消费者的解耦。

结合前面所说的问题:

  • 商品服务对商品增删改以后,无需去操作索引库或静态页面,只是发送一条消息,也不关心消息被谁接收。
  • 搜索服务和静态页面服务接收消息,分别去处理索引库和静态页面。

如果以后有其它系统也依赖商品服务的数据,同样监听消息即可,商品服务无需任何代码修改。

1.2.2.AMQP和JMS

MQ是消息通信的模型,并不是具体实现。现在实现MQ的有两种主流方式:AMQP、JMS。

两者间的区别和联系:

  • JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式
  • JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。
  • JMS规定了两种消息模型;而AMQP的消息模型更加丰富

1.2.3.常见MQ产品

  • ActiveMQ:基于JMS
  • RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好
  • RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会
  • Kafka:分布式消息系统,高吞吐量

1.2.4.RabbitMQ

RabbitMQ是基于AMQP的一款消息管理系统

官网: http://www.rabbitmq.com/

官方教程:http://www.rabbitmq.com/getstarted.html

1.3.下载和安装

参考另一篇博客:rabbitMQ安装
https://blog.csdn.net/qq_38454176/article/details/105338529

2.五种消息模型

RabbitMQ提供了6种消息模型,但是第6种其实是RPC,并不是MQ,因此不予学习。那么也就剩下5种。

RabbitMQ的具体学习和使用,请看另一篇博客:
day72 JavaWeb框架阶段——RabbitMQ消息队列
https://blog.csdn.net/qq_38454176/article/details/105339764

3.项目改造

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

3.1.思路分析

发送方:商品微服务

  • 什么时候发?

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

  • 发送什么内容?

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

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

接收消息后如何处理?

  • 搜索微服务:

    • 增/改:添加新的数据到索引库
    • 删:删除索引库数据
  • 静态页微服务:
    • 增/改:创建新的静态页
    • 删:删除原来的静态页

3.2.商品服务发送消息

我们先在商品微服务leyou-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.101username: leyoupassword: leyouvirtual-host: /leyoutemplate:exchange: leyou.item.exchangepublisher-confirms: true
  • template:有关AmqpTemplate的配置

    • exchange:缺省的交换机名称,此处配置后,发送消息如果不指定交换机就会使用这个
  • publisher-confirms:生产者确认机制,确保消息会正确发送,如果发送失败会有错误回执,从而触发重试

3.2.3.改造GoodsService

在GoodsService中封装一个发送消息到mq的方法:(需要注入AmqpTemplate模板)

private void sendMessage(Long id, String type){// 发送消息try {this.amqpTemplate.convertAndSend("item." + type, id);} catch (Exception e) {logger.error("{}商品消息发送异常,商品id:{}", type, id, e);}
}

这里没有指定交换机,因此默认发送到了配置中的:leyou.item.exchange

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

然后在新增的时候调用:

修改的时候调用:

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.101username: leyoupassword: leyouvirtual-host: /leyou

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

3.3.3.编写监听器

代码:

@Component
public class GoodsListener {@Autowiredprivate SearchService searchService;/*** 处理insert和update的消息** @param id* @throws Exception*/@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "leyou.create.index.queue", durable = "true"),exchange = @Exchange(value = "leyou.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 = "leyou.delete.index.queue", durable = "true"),exchange = @Exchange(value = "leyou.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) throws IOException {Spu spu = this.goodsClient.querySpuById(id);// 构建商品Goods goods = this.buildGoods(spu);// 保存数据到索引库this.goodsRepository.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.101username: leyoupassword: leyouvirtual-host: /leyou

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

3.4.3.编写监听器

代码:

@Component
public class GoodsListener {@Autowiredprivate GoodsHtmlService goodsHtmlService;@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "leyou.create.web.queue", durable = "true"),exchange = @Exchange(value = "leyou.item.exchange",ignoreDeclarationExceptions = "true",type = ExchangeTypes.TOPIC),key = {"item.insert", "item.update"}))public void listenCreate(Long id) throws Exception {if (id == null) {return;}// 创建页面goodsHtmlService.createHtml(id);}@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "leyou.delete.web.queue", durable = "true"),exchange = @Exchange(value = "leyou.item.exchange",ignoreDeclarationExceptions = "true",type = ExchangeTypes.TOPIC),key = "item.delete"))public void listenDelete(Long id) {if (id == null) {return;}// 删除页面goodsHtmlService.deleteHtml(id);}
}

3.4.4.添加删除页面方法

public void deleteHtml(Long id) {File file = new File("C:\\project\\nginx-1.14.0\\html\\item\\", id + ".html");file.deleteOnExit();
}

3.5.测试

3.5.1.查看RabbitMQ控制台

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

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

队列也已经创建完毕:

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

3.5.2.修改数据试一试

在后台修改商品数据的价格,分别在搜索及商品详情页查看是否统一。

【javaWeb微服务架构项目——乐优商城day11】——利用RabbitMQ实现搜索和静态页的数据同步相关推荐

  1. 【javaWeb微服务架构项目——乐优商城day15】——会调用订单系统接口,实现订单结算功能,实现微信支付功能

    0.学习目标 会调用订单系统接口 实现订单结算功能 实现微信支付功能 源码笔记及资料: 链接:https://pan.baidu.com/s/1_opfL63P1pzH3rzLnbFiNw 提取码:v ...

  2. 【javaWeb微服务架构项目——乐优商城day03】——(搭建后台管理前端,Vuetify框架,使用域名访问本地项目,实现商品分类查询,cors解决跨域,品牌的查询)

    乐优商城day03 0.学习目标 1.搭建后台管理前端 1.1.导入已有资源 1.2.安装依赖 1.3.运行一下看看 1.4.目录结构 1.5.调用关系 2.Vuetify框架 2.1.为什么要学习U ...

  3. 【javaWeb微服务架构项目——乐优商城day05】——商品规格参数管理(增、删、改,查已完成),SPU和SKU数据结构,商品查询

    乐优商城day05 0.学习目标 1.商品规格数据结构 1.1.SPU和SKU 1.2.数据库设计分析 1.2.1.思考并发现问题 1.2.2.分析规格参数 1.2.3.SKU的特有属性 1.2.4. ...

  4. 【javaWeb微服务架构项目——乐优商城day07】——Elasticsearch介绍和安装及使用(安装kibana,安装ik分词器,Spring Data Elasticsearch,高级查询)

    文章目录 0.学习目标 1.Elasticsearch介绍和安装 1.1.简介 1.1.1.Elastic 1.1.2.Elasticsearch 1.1.3.版本 1.2.安装和配置 1.2.1.新 ...

  5. 微服务框架 SpringCloud微服务架构 25 黑马旅游案例 25.5 排序和搜索关键字高亮

    微服务框架 [SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务] SpringCloud微服务 ...

  6. 终极对决!Dubbo 和 Spring Cloud 微服务架构到底孰优孰劣?

    微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...

  7. blog微服务架构代码_DDD+微服务大型案例:Uber如何从复杂的RPC微服务转向面向业务领域的微服务架构DOMA? -优步工程博客...

    最近,围绕面向服务的体系结构,尤其是微服务体系结构的弊端进行了大量讨论.仅仅几年前,由于许多人宣传微服务架构的好处,例如独立部署形式的灵活性,明确的所有权,系统稳定性的改进以及更好的关注点分离,很多人 ...

  8. Java实战项目——乐优商城 常见错误集锦(一) ERROR com.zaxxer.hikari.pool.HikariPool:HikariPool-1-Exception during pool

    前言 错误信息:com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - 在初始化期间出现异常,具体异常信息如下: mysql连接出现问题?经过查阅资料,出 ...

  9. 《黑马头条》SpringBoot+SpringCloud+ Nacos等企业级微服务架构项目

    01环境搭建.SpringCloud微服务(注册发现.服务调用.网关) 1)课程对比 2)项目概述 2.1)能让你收获什么 2.2)项目课程大纲 2.3)项目概述 随着智能手机的普及,人们更加习惯于通 ...

最新文章

  1. C#中使用DirectX编程
  2. LeetCode 319. Bulb Switcher--C++,java,python 1行解法--数学题
  3. Xshell 连接ubuntu16.04 32位
  4. springboot通过接口访问html,springboot不通过controller直接访问静态html
  5. 小姐姐为你解析马爸爸是怎么用大数据“宰你”的
  6. 《Leetcode》目录
  7. 【LeetCode】【HOT】236. 二叉树的最近公共祖先(递归)
  8. JVM老年代垃圾收集器Serial Old和Parallel Old
  9. spark yarn 提交作业
  10. type(img).__module__ == np.__name__
  11. 只要学会这个PDF压缩方法,压缩PDF不再是难题
  12. Web自动化框架LazyUI使用手册(4)--控件抓取工具Elements Extractor详解(批量抓取)
  13. SAP MM采购信息记录作用与浅析
  14. 科技企业的技术文化为什么难写?
  15. 存储空间不足,无法完成此操作
  16. 2018noip模拟 烷基
  17. 计算机上计算器不见,win10系统自带的计算器不见了的处理教程
  18. Allegro自动对齐工具
  19. android实现气泡聊天
  20. InnoDB执行delete时到底做了什么?

热门文章

  1. 论文解读:利用结构隐代码的隐神经表示方法来合成动态人体的新颖视角
  2. C语言查看大小端(纯代码)
  3. Markdown教程--Markdown表格
  4. 赛元科技EasyCodeCube的使用——新建一个工程
  5. 特斯拉Model Y在美国降价2万元,略贵于Model 3
  6. 网络之路由器工作原理
  7. C语言实现strncpy函数
  8. motionFX ST意法半导体X-MEMS运动融合库
  9. 在WPS,表格中如何将选中的单元格行和列高亮显示
  10. 阿里云 kbe frp