首页 > 其他 > 详细

039 RabbitMq及数据同步

时间:2019-10-05 12:45:34      阅读:109      评论:0      收藏:0      [点我收藏+]

1.RabbitMq

(1)问题引出

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

  • 商品的原始数据保存在数据库中,增删改查都在数据库中完成。

  • 搜索服务数据来源是索引库,如果数据库商品发生变化,索引库数据不能及时更新

  • 商品详情做了页面静态化,静态页面数据也不会随着数据库商品发生变化。

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

这里有两种解决方案:

  • 方案1:每当后台对商品做增删改操作,同时要修改索引库数据及静态页面

  • 方案2:搜索服务和商品页面服务对外提供操作接口,后台在商品增删改后,调用接口

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

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

 (2)消息队列

<1>什么是消息队列

消息队列,即MQ,Message Queue。

技术分享图片

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

结合前面所说的问题:

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

  • 搜索服务和静态页面服务接收消息,分别去处理索引库和静态页面。

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

<2>AMQP和JMS

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

技术分享图片

 

 技术分享图片

两者间的区别和联系:

  • JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式

  • JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。

  • JMS规定了两种消息模型;而AMQP的消息模型更加丰富

<3>常见MQ产品

技术分享图片

 

  • ActiveMQ:基于JMS

  • RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好

  • RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会

  • Kafka:分布式消息系统,高吞吐量

<4>RabbitMQ

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

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

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

技术分享图片

 

技术分享图片

(3)下载与安装(windows环境)

<1>下载安装

RabbitMQ由Erlang语言开发,Erlang语言用于并发及分布式系统的开发,在电信领域应用广泛,OTP(Open Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件及工具库,安装RabbitMQ需要安装Erlang/OTP,并保持版本匹配,如下图:

RabbitMQ的下载地址:http://www.rabbitmq.com/download.html

技术分享图片

 

本项目使用Erlang/OTP 20.3版本和RabbitMQ3.7.3版本。

技术分享图片

1)下载erlang
地址如下:
http://erlang.org/download/otp_win64_20.3.exe,以管理员方式运行此文件,安装。

技术分享图片

技术分享图片

技术分享图片
erlang安装完成需要配置erlang环境变量: ERLANG_HOME=D:\Program Files\erl9.3  在path中添加%ERLANG_HOME%\bin;

此电脑-->鼠标右键“属性”-->高级系统设置-->环境变量-->“新建”系统环境变量

技术分享图片

变量名:ERLANG_HOME

变量值就是刚才erlang的安装地址,点击确定。

然后双击系统变量path

技术分享图片

 

点击“新建”,将%ERLANG_HOME%\bin加入到path中。

技术分享图片

最后windows键+R键,输入cmd,再输入erl,看到版本号就说明erlang安装成功了。

技术分享图片

2)安装RabbitMQ
https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.3,以管理员方式运行此文件,安装。

技术分享图片

 

技术分享图片

<2>启动
安装成功后会自动创建RabbitMQ服务并且启动。
1)从开始菜单启动RabbitMQ
完成在开始菜单找到RabbitMQ的菜单:

技术分享图片

RabbitMQ Service-install :安装服务
RabbitMQ Service-remove 删除服务
RabbitMQ Service-start 启动
RabbitMQ Service-stop 停止

2)如果没有开始菜单则进入安装目录下sbin目录手动启动:

技术分享图片

  1)安装并运行服务
  rabbitmq-service.bat install 安装服务 rabbitmq-service.bat stop 停止服务 rabbitmq-service.bat start 启动服务

  2)安装管理插件
  安装rabbitMQ的管理插件,方便在浏览器端管理RabbitMQ
  管理员身份运行 rabbitmq-plugins.bat enable rabbitmq_management

技术分享图片

安装完插件后,需要重启rabbitmq,此电脑-->鼠标右键“管理”-->服务与应用程序-->服务

技术分享图片

打开sbin目录,双击rabbitmq-server.bat

技术分享图片

 

等几秒钟看到这个界面后,访问http://localhost:15672

初始账号和密码:guest/guest

技术分享图片

 

技术分享图片

<3>注意事项

  1. 安装erlang和rabbitMQ以管理员身份运行。
  2. 当卸载重新安装时会出现RabbitMQ服务注册失败,此时需要进入注册表清理erlang搜索RabbitMQ、ErlSrv,将对应的项全部删除。

2.五种消息模型

 

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

 

但是其实3、4、5这三种都属于订阅模型,只不过进行路由的方式不同。

技术分享图片

 

我们通过一个demo工程来了解下RabbitMQ的工作方式:

向已存在的工程导入模块:

技术分享图片

技术分享图片

技术分享图片

技术分享图片

 

技术分享图片

技术分享图片

导入成功后,模块的结构:

技术分享图片

package cn.itcast.rabbitmq.simple;

import cn.itcast.rabbitmq.util.ConnectionUtil;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
/**
 * 生产者
 */
public class Send {

    private final static String QUEUE_NAME = "simple_queue";

    public static void main(String[] argv) throws Exception {
        // 获取到连接
        Connection connection = ConnectionUtil.getConnection();
        // 从连接中创建通道,使用通道才能完成消息相关的操作
        Channel channel = connection.createChannel();
        // 声明(创建)队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        // 消息内容
        String message = "Hello World!";
        // 向指定的队列中发送消息
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        
        System.out.println(" [x] Sent ‘" + message + "‘");

        //关闭通道和连接
        channel.close();
        connection.close();
    }
}

(1)基本消息模型

RabbitMQ是一个消息代理:它接受和转发消息。 你可以把它想象成一个邮局:当你把邮件放在邮箱里时,你可以确定邮差先生最终会把邮件发送给你的收件人。 在这个比喻中,RabbitMQ是邮政信箱,邮局和邮递员。

RabbitMQ与邮局的主要区别是它不处理纸张,而是接受,存储和转发数据消息的二进制数据块。

技术分享图片

 

P(producer/ publisher):生产者,一个发送消息的用户应用程序。

C(consumer):消费者,消费和接收有类似的意思,消费者是一个主要用来等待接收消息的用户应用程序

队列(红色区域):rabbitmq内部类似于邮箱的一个概念。虽然消息流经rabbitmq和你的应用程序,但是它们只能存储在队列中。队列只受主机的内存和磁盘限制,实质上是一个大的消息缓冲区。许多生产者可以发送消息到一个队列,许多消费者可以尝试从一个队列接收数据。

总之:

生产者将消息发送到队列,消费者从队列中获取消息,队列是存储消息的缓冲区。

我们将用Java编写两个程序;发送单个消息的生产者,以及接收消息并将其打印出来的消费者。我们将详细介绍Java API中的一些细节,这是一个消息传递的“Hello World”。

我们将调用我们的消息发布者(发送者)Send和我们的消息消费者(接收者)Recv。发布者将连接到RabbitMQ,发送一条消息,然后退出。

<1>生产者发送消息

public class Send {

    private final static String QUEUE_NAME = "simple_queue";

    public static void main(String[] argv) throws Exception {
        // 获取到连接以及mq通道
        Connection connection = ConnectionUtil.getConnection();
        // 从连接中创建通道,这是完成大部分API的地方。
        Channel channel = connection.createChannel();

        // 声明(创建)队列,必须声明队列才能够发送消息,我们可以把消息发送到队列中。
        // 声明一个队列是幂等的 - 只有当它不存在时才会被创建
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        // 消息内容
        String message = "Hello World!";
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        System.out.println(" [x] Sent ‘" + message + "‘");

        //关闭通道和连接
        channel.close();
        connection.close();
    }
}

控制台:

技术分享图片

 

039 RabbitMq及数据同步

原文:https://www.cnblogs.com/luckyplj/p/11624357.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!