1. RabbitMQ
1.1. 搜索与商品服务的问题
假设我们已经完成了商品详情和搜索系统的开发。我们思考一下,是否存在问题?
o 商品的原始数据保存在数据库中,增删改查都在数据库中完成。
o 搜索服务数据来源是索引库,如果数据库商品发生变化,索引库数据能否及时更新。
如果我们在后台修改了商品的价格,搜索页面依然是旧的价格,这样显然不对。该如何解决?
这里有两种解决方案:
o 方案1:每当后台对商品做增删改操作,同时要修改索引库数据
o 方案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规定了两种消息模型(queue, topic);而AMQP的消息模型更加丰富
1.2.3. 常见MQ产品
• ActiveMQ:基于JMS
• RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好
• RocketMQ:基于JMS,阿里巴巴产品,目前交由Apache基金会
• Kafka:分布式消息系统,高吞吐量,处理日志,Scala和Java编写,Apache
1.2.4. RabbitMQ
• RabbitMQ是基于AMQP的一款消息管理系统
o 官网: http://www.rabbitmq.com/
o 官方教程:http://www.rabbitmq.com/getstarted.html
• RabbitMQ是一个开源的,在AMQP基础上完成的,可服用的企业消息系统。
• 支持主流的操作系统,Linux,Windows,MacOX等
• 多种开发语言支持,Java,Python,Ruby,.Net,PHP,C/C++,node.js等
1.2.5. MQ三大主要功能
• 异步
• 解耦
• 削峰
1.2.6 RabbitMQ 特点
• RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。
• 可靠性(Reliability)
RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
• 灵活的路由(Flexible Routing)
在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
• 消息集群(Clustering)
多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。
• 高可用(Highly Available Queues)
队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
• 多种协议(Multi-protocol)
RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。
• 多语言客户端(Many Clients)
RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。
• 管理界面(Management UI)
RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。
• 跟踪机制(Tracing)
如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。
• 插件机制(Plugin System)
RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。
1.2.7 RabbitMQ 基本概念
上面只是最简单抽象的描述,具体到 RabbitMQ 则有更详细的概念需要解释。上面介绍过 RabbitMQ 是 AMQP 协议的一个开源实现,所以其内部实际上也是 AMQP 中的基本概念:
Message
消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
Publisher
消息的生产者,也是一个向交换器发布消息的客户端应用程序。
Exchange
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
Binding
绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
Queue
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
Connection
网络连接,比如一个TCP连接。
Channel
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
Consumer
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。
Broker
表示消息队列服务器实体。
1.3. 下载和安装
1.3.1. 下载
1.下载Erlang的rpm包
RabbitMQ是Erlang语言编写,所以Erang环境必须要有,注:Erlang环境一定要与RabbitMQ版本匹配:https://www.rabbitmq.com/which-erlang.html
Erlang下载地址:https://www.rabbitmq.com/releases/erlang/(根据自身需求及匹配关系,下载对应rpm包)
https://dl.bintray.com/rabbitmq-erlang/rpm/erlang/21/el/7/x86_64/erlang-21.3.8.9-1.el7.x86_64.rpm
2.下载socat的rpm包
rabbitmq安装依赖于socat,所以需要下载socat。
socat下载地址:http://repo.iotti.biz/CentOS/7/x86_64/socat-1.7.3.2-5.el7.lux.x86_64.rpm
3.下载RabbitMQ的rpm包
RabbitMQ下载地址:https://www.rabbitmq.com/download.html(根据自身需求及匹配关系,下载对应rpm包)rabbitmq-server-3.8.1-1.el7.noarch.rpm
1.3.2. 安装
1.安装Erlang、Socat、RabbitMQ
①rpm -ivh erlang-21.3.8.9-1.el7.x86_64.rpm
②rpm -ivh socat-1.7.3.2-1.el6.lux.x86_64.rpm
在安装rabbitmq之前需要先安装socat,否则,报错。
可以采用yum安装方式:yum install socat,我们这里采用rpm安装方式
③rpm -ivh rabbitmq-server-3.8.1-1.el7.noarch.rpm
/usr/lib/rabbitmq/lib/rabbitmq_server-3.8.1/sbin
2.启用管理插件
rabbitmq-plugins enable rabbitmq_management
3.启动RabbitMQ
systemctl start rabbitmq-server.service
systemctl status rabbitmq-server.service
systemctl restart rabbitmq-server.service
systemctl stop rabbitmq-server.service
4.查看进程
ps -ef | grep rabbitmq
1.3.3. 测试
o 关闭防火墙:systemctl stop firewalld.service
o 在web浏览器中输入地址:http://虚拟机ip:15672/
o 输入默认账号密码: guest : guest,guest用户默认不允许远程连接。
o 增加自定义账号
o 添加管理员账号密码:rabbitmqctl add_user admin admin
o 分配账号角色:rabbitmqctl set_user_tags admin administrator
o 修改密码:rabbitmqctl change_password admin 123456
o 查看用户列表:rabbitmqctl list_users
o 使用新账号登录,成功界面
o 管理界面标签页介绍
o overview:概览
o connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况
o channels:通道,建立连接后,会形成通道,消息的投递获取依赖通道。
o Exchanges:交换机,用来实现消息的路由
o Queues:队列,即消息队列,消息存放在队列中,等待消费,消费后被移除队列。
o 端口:
• 5672:rabbitMq的编程语言客户端连接端口
• 15672:rabbitMq管理界面端口
• 25672:rabbitMq集群的端口
1.3.4. 卸载
• rpm -qa | grep rabbitmq
• rpm -e rabbitmq-server
1.4. 管理界面
1.4.1. 添加用户
如果不使用guest,我们也可以自己创建一个用户:
1、 超级管理员(administrator)
可登录管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
2、 监控者(monitoring)
可登录管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
3、 策略制定者(policymaker)
可登录管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
4、 普通管理者(management)
仅可登录管理控制台,无法看到节点信息,也无法对策略进行管理。
5、 其他
无法登录管理控制台,通常就是普通的生产者和消费者。
1.4.2. 创建Virtual Hosts
虚拟主机:类似于mysql中的database。他们都是以“/”开头