RabbitMq--01

一、什么是RabbitMQ?用它能做什么?

1.简介

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。

2.作用

消息中间件之间解耦,以网上商城为例,用户下单时可能会有大并发量,服务器压力也会增大,特别是类似双11的时候,那如何解决呢?可以使用消息队列将订单信息放在队列中,下单后付款需要把订单信息传给仓库并会发送短信或者邮箱,仓库这边又联系着进销存系统,这样如果把网上商城系统和进销存系统都放在一起,那就会更加庞大不利于系统解耦,体现不了高内聚低耦合的思想。同时会把订单信息通过邮箱或者短信发送给用户,这样会调用发送邮件或短信的系统,发送邮件或短信的速度速度有限,高峰时可能会将服务器爆了,这种情况可以使用消息队列来起到错峰的作用。

二、名词介绍

1.ConnectionFactory、Connection、Channel

ConnectionFactory从名词可以看出Connection工厂,它主要用来创建Connection。Connection客户端与服务器打交道需要先创建与服务器的链接,然后通过管道Channel来进行操作。

2.Queue队列

RabbitMQ中的消息都只能存储在Queue中,相同属性的queue可以重复定义,有以下几个属性。
- 持久性:如果启用,队列将会在server重启前都有效。
- 自动删除:如果启用,那么队列将会在所有的消费者停止使用之后自动删除掉自身。
- 惰性:如果没有声明队列,那么在执行到使用的时候会导致异常,并不会主动声明。
- 排他性:如果启用,队列只能被声明它的消费者使用

3.生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题,生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。一个生产者可以有多个消费者,例如上面的网上商城的例子中,生产者是网上商城系统的订单,消费者是仓库系统、邮件、短信服务系统以及日志系统等。

4.Message acknowledgment消息回执

比如在下单过程中用户下单后需要给仓库进销存系统、邮件服务系统、日志系统等,而每个系统又会创建多个消费者,此时消息队列并不会就把消息删除,而是需要发送一个回执,以防止消费者宕机等原因导致消息丢失。这里有一个需要注意的地方就是这里没有timeout超时的概念,一个消费者处理消息时间再长也不会导致该消息被发送给其他消费者(多个消费者),除非它的RabbitMQ连接断开,在消费者消费之后要记得发送回执,不然会一直堆积在队列中,消费者重启后会重复消费这些消息并重复执行业务逻辑。

5.持久化

RabbitMQ服务器也有重启或宕机的可能性,为了不让消息丢失,我们可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。

6.Prefetch count

使用Prefetch count可以实现负载均衡,多个消费者消费一个消息队列时,可能每个消费者处理信息的时间快慢不同,不能让有的累死有的饿死,可以通过设置Prefetch count=1,Queue每次给每个消费者发送一条消息;消费者处理完这条消息后Queue会再给该消费者发送一条消息。

7.Exchange交换机

从名词理解,类似网络的交换机,还是以订单为例,生产者网上商城生产的消息需要给仓库进销存系统,邮件系统,日志系统,而每个系统又可以创建多个消费者来处理,每个系统不可能都操作一个消息队列,那样的话任何一个消费者系统发送回执就会导致消息丢失,导致其他系统遗漏信息处理,实际上一般是会把消息发给交换机,由Exchange将消息路由到一个或多个Queue中(或者丢弃)。这样进销存、邮件、日志系统都分别会有一个消息队列,这样就不会导致消息丢失了。

8.Binding、Binding key、routing key

Exchange将消息路由到一个或多个Queue,那如何与消息队列发生关系呢?那就需要先将消息队列与交换机绑定到一起,一般会指定一个binding key。当消息队列与交换机绑定之后,消费者就可以生产消息传递给消息队列,那各个消息如何进入到不同的队列呢?生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联合使用才能最终生效。在Exchange Type与binding key固定的情况下(在正常使用时一般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange时,通过指定routing key来决定消息流向哪里。当binding key与routing key相匹配时,消息将会被路由到对应的Queue中。RabbitMQ为routing key设定的长度限制为255 bytes。binding key 并不是在所有情况下都生效,它依赖于Exchange Type,比如fanout类型的Exchange就会无视binding key,而是将消息路由到所有绑定到该Exchange的Queue.

9.Exchange Types

RabbitMQ一般的Exchange Type有fanout、direct、topic、headers这四种。fanout、direct、topic比较常用headers并不常用。

1.fanout:它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中.

2.direct: DirectExchange是RabbitMQ Broker的默认Exchange,它有一个特别的属性对一些简单的应用来说是非常有用的,在使用这个类型的Exchange时,可以不必指定routing key的名字,在此类型下创建的Queue有一个默认的routing key,这个routing key一般同Queue同名。

3.topic:direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定:

1)、routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词)
2)、binding key与routing key一样也是句点号“. ”分隔的字符串 binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)

 

---------------我是有底线的-------------------- 
作者:社会主义接班人
出处:http://www.cnblogs.com/5ishare/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果文中有什么错误,欢迎指出。以免更多的人被误导。
<think>我们被要求详细解释两条Docker命令: 1. `mkdir -p /data/rabbitmq-data` 2. `docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data --opt o=bind cluster<01,02,03>-rabbitmq-data` 首先,我们逐条解释: 第一条命令:`mkdir -p /data/rabbitmq-data` - `mkdir`:创建目录的命令。 - `-p`:选项,表示如果路径中的父目录不存在,则创建它们(递归创建)。 - `/data/rabbitmq-data`:要创建的目录路径。 这条命令的作用是在宿主机的根目录下创建`/data/rabbitmq-data`目录(如果`/data`目录不存在,也会被创建),用于存放RabbitMQ的数据。 第二条命令:`docker volume create ...` 这条命令用于创建一个Docker卷。我们分解选项: - `--driver local`:指定使用本地驱动程序创建卷。这是默认的驱动程序,意味着卷将存储在宿主机的文件系统上。 - `--opt type=none`:指定挂载类型为`none`,这通常表示我们将使用一个预先存在的目录作为卷的源。 - `--opt device=/data/rabbitmq-data`:指定设备(即宿主机上的目录路径)为`/data/rabbitmq-data`。这个目录就是上一条命令创建的目录。 - `--opt o=bind`:指定挂载选项为`bind`,这表示将使用绑定挂载(bind mount)的方式将宿主机的目录挂载到容器中。 - `cluster<01,02,03>-rabbitmq-data`:这是卷的名称。注意,这里使用了尖括号和逗号分隔的列表,但实际上在Docker卷名称中是不允许这样命名的。这里可能是用户想创建多个卷(分别对应cluster01, cluster02, cluster03)的一个示例表示,但实际命令中应该是分别创建三个卷,例如: docker volume create ... cluster01-rabbitmq-data docker volume create ... cluster02-rabbitmq-data docker volume create ... cluster03-rabbitmq-data 因为卷名必须是唯一的,且不能包含逗号和尖括号。因此,我们猜测用户意图是创建三个类似的卷,分别命名为`cluster01-rabbitmq-data`、`cluster02-rabbitmq-data`和`cluster03-rabbitmq-data`,每个卷分别绑定到宿主机的不同目录(例如`/data/rabbitmq-data01`等)或者同一个目录(但通常不会,因为这样会冲突)。但根据命令中的`device`参数是同一个目录,这显然是不合理的,因为多个卷不能同时绑定到同一个宿主机目录(除非只创建一个卷,然后多个容器共享)。所以这里可能是用户想为三个节点分别创建三个目录和三个卷。 因此,我们更合理的解释是:用户可能想为三个RabbitMQ节点分别创建数据目录和卷。所以实际命令应该是三条,每条命令分别对应一个节点,例如: 对于节点1: mkdir -p /data/rabbitmq-data01 docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data01 --opt o=bind cluster01-rabbitmq-data 节点2: mkdir -p /data/rabbitmq-data02 docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data02 --opt o=bind cluster02-rabbitmq-data 节点3: mkdir -p /data/rabbitmq-data03 docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data03 --opt o=bind cluster03-rabbitmq-data 但是,如果用户希望三个节点共享同一个数据目录(但通常RabbitMQ集群每个节点需要独立的数据目录),那么使用同一个目录会导致数据冲突。所以,我们按照每个节点独立目录来理解。 然而,用户给出的命令中只创建了一个目录,而卷名中却包含了三个名字,这可能是笔误。因此,我们重点解释单条命令的含义。 现在,我们重新解释第二条命令(假设卷名是`cluster01-rabbitmq-data`): - 这条命令创建了一个名为`cluster01-rabbitmq-data`的Docker卷。 - 这个卷的类型是本地卷(local),并且使用绑定挂载(bind mount)方式将宿主机的`/data/rabbitmq-data`目录挂载到容器中。 - 当我们在运行容器时使用这个卷(如`-v cluster01-rabbitmq-data:/var/lib/rabbitmq`),容器内的`/var/lib/rabbitmq`目录实际上就是宿主机的`/data/rabbitmq-data`目录。 绑定挂载的特点: - 宿主机上的目录必须存在,所以需要先使用`mkdir`命令创建。 - 容器和宿主机之间对该目录的读写是实时同步的。 - 这种方式便于在宿主机上直接查看或修改数据(例如备份、恢复等)。 总结: - 第一条命令在宿主机上创建了一个目录,用于持久化存储数据。 - 第二条命令创建了一个Docker卷,该卷将宿主机上的这个目录绑定到容器中,以便容器使用。 这样做的目的是为了数据的持久化,即使容器被删除,宿主机上的数据仍然存在。同时,也方便在多个容器之间共享数据(但注意,多个容器同时写入同一个目录可能会导致问题,需要应用程序支持共享)。 注意:在RabbitMQ集群中,每个节点通常需要独立的数据目录,所以我们应该为每个节点创建独立的目录和卷。 因此,我们给出更符合实际集群部署的建议命令: 1. 创建三个目录: mkdir -p /data/rabbitmq-data01 mkdir -p /data/rabbitmq-data02 mkdir -p /data/rabbitmq-data03 2. 创建三个卷,分别绑定到这三个目录: docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data01 --opt o=bind cluster01-rabbitmq-data docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data02 --opt o=bind cluster02-rabbitmq-data docker volume create --driver local --opt type=none --opt device=/data/rabbitmq-data03 --opt o=bind cluster03-rabbitmq-data 然后,在运行三个RabbitMQ容器时,分别使用对应的卷。 以上是对用户命令的详细解释。 </think> ### 详细解释 Docker 目录创建与卷绑定命令 #### 1. **`mkdir -p /data/rabbitmq-data`** ```bash mkdir -p /data/rabbitmq-data ``` - **作用**: 在宿主机上创建目录树,用于持久化存储 RabbitMQ 数据。 - **参数解析**: - `-p`:递归创建目录(若父目录 `/data` 不存在则自动创建)。 - `/data/rabbitmq-data`:宿主机目录路径,用于存储 RabbitMQ 的队列、消息等数据。 - **重要性**: 避免容器删除后数据丢失,实现数据持久化[^4]。目录结构示例如下: ``` /data └── rabbitmq-data ├── mnesia # RabbitMQ 数据库文件 └── logs # 日志文件 ``` --- #### 2. **`docker volume create` 命令** ```bash docker volume create \ --driver local \ --opt type=none \ --opt device=/data/rabbitmq-data \ --opt o=bind \ cluster01-rabbitmq-data ``` - **核心作用**: 创建名为 `cluster01-rabbitmq-data` 的 Docker 卷,将宿主机目录 `/data/rabbitmq-data` **绑定挂载**到容器内。 - **参数解析**: - `--driver local`:使用本地存储驱动(默认类型)[^4]。 - `--opt type=none`:指定卷类型为普通目录(非特殊文件系统)。 - `--opt device=/data/rabbitmq-data`:宿主机目录路径(需提前通过 `mkdir` 创建)[^4]。 - `--opt o=bind`:挂载方式为 **bind mount**(宿主机与容器目录实时双向同步)。 - `cluster01-rabbitmq-data`:自定义卷名称(实际使用需替换 `<01,02,03>` 为具体节点编号)。 - **绑定挂载原理**: ![](https://docs.docker.com/storage/images/types-of-mounts-bind.png) 宿主机目录与容器目录直接映射,所有修改实时同步[^4]。 --- ### 完整工作流程示例(RabbitMQ 集群节点) ```bash # 1. 创建宿主机目录 mkdir -p /data/rabbitmq-data01 # 2. 创建绑定卷 docker volume create \ --driver local \ --opt type=none \ --opt device=/data/rabbitmq-data01 \ --opt o=bind \ cluster01-rabbitmq-data # 3. 启动容器并挂载卷 docker run -d \ --name rabbitmq01 \ -v cluster01-rabbitmq-data:/var/lib/rabbitmq \ # 挂载点 rabbitmq:3.8-management ``` - **关键挂载点**: `-v cluster01-rabbitmq-data:/var/lib/rabbitmq` 将卷映射到容器内的 RabbitMQ 数据目录[^3][^4]。 --- ### 常见问题解答 1. **为何不直接使用 `-v /宿主机路径:/容器路径`?** 显式创建卷(`docker volume create`)便于集中管理卷(通过 `docker volume ls` 查看),适合生产环境维护。 2. **多节点集群如何配置?** 为每个节点创建独立目录和卷(如 `cluster02-rabbitmq-data`、`cluster03-rabbitmq-data`),避免数据冲突。 3. **权限错误如何处理?** 确保宿主机目录权限(如 `chown 999:999 /data/rabbitmq-data`),RabbitMQ 容器默认使用 UID 999 运行[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值