OpenStack共享组件-RabbitMQ消息队列
1. MQ
全称为 Message Queue, 消息队列( MQ ),是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。
消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。
排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。
2. AMQP
即 Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布 / 订阅)、可靠性、安全。
3. RabbitMQ
属于一个流行的开源消息队列系统。属于AMQP( 高级消息队列协议 ) 标准的一个 实现。是应用层协议的一个开放标准,为面向消息的中间件设计。用于在分布式系统中存储转发消息,在 易用性、扩展性、高可用性等方面表现不俗。
消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
RabbitMQ特点:
使用Erlang编写;
支持持久化;
支持HA;
提供C# , erlang,java,perl,python,ruby等的client开发端。
4. 什么是耦合、解耦合
1> 耦合
耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。
在软件工程中,对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护成本越高,因此对象的设计应使类和构件之间的耦合最小。
分类:有软硬件之间的耦合,还有软件各模块之间的耦合。耦合性是程序结构中各个模块之间相互关联的度量。它取决于各个模块之间的接口的复杂程度、调用模块的方式以及哪些信息通过接口。
2> 解耦
解耦,字面意思就是解除耦合关系。
在软件工程中,降低耦合度即可以理解为解耦,模块间有依赖关系必然存在耦合,理论上的绝对零耦合是做不到的,但可以通过一些现有的方法将耦合度降至最低。
设计的核心思想:尽可能减少代码耦合,如果发现代码耦合,就要采取解耦技术。让数据模型,业务逻辑和视图显示三层之间彼此降低耦合,把关联依赖降到最低,而不至于牵一发而动全身。原则就是A功能的代码不要写在B的功能代码中,如果两者之间需要交互,可以通过接口,通过消息,甚至可以引入框架,但总之就是不要直接交叉写。
5. RabbitMQ中的概念名词
Broker:简单来说就是消息队列服务器实体。
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个
channel代表一个会话任务。
6. RabbitMQ工作原理
MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取或者订阅队列中的消息。MQ则是遵循了AMQP协议的具体实现和产品。在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
1)客户端连接到消息队列服务器,打开一个channel。
2)客户端声明一个exchange,并设置相关属性。
3)客户端声明一个queue,并设置相关属性。
4)客户端使用routing
key,在exchange和queue之间建立好绑定关系。
5)客户端投递消息到exchange。
6)exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。
7. RabbitMQ的metadata(元数据)
元数据可以持久化在RAM或Disc,从这个角度可以把RabbitMQ集群中的节点分成两种:RAM Node和Disk Node。
RAM Node 只会将元数据存放在RAM(内存);
Disk Node 会将元数据持久化到磁盘。
单节点系统就没有什么选择了,只允许disk node,否则由于没有数据冗余一旦重启就会丢掉所有的配置信息。但在集群环境中可以选择哪些节点是RAM node,在集群中声明(declare)创建exchange queue binding这类操作要等到所有的节点都完成创建才会返回。
如果是内存节点就要修改内存数据;
如果是 disk node 就要等待写磁盘,节点过多这里的速度就会被大大的拖慢。
有些场景exchang queue相当固定 , 变动很少 ,那即使全都是 disc node, 也没有什么影响 . 如果使用 Rabbitmq 做 RPC( RPC :Remote Procedure Call—远程过程调用), RPC 或者类似 RPC 的场景这个问题就严重了 , 频繁创建销毁临时队列 , 磁盘读写能力就很快成为性能瓶颈了。所以 , 大多数情况下 , 我们尽量把 Node 创建为RAM Node. 这里就有一个问题了 , 要想集群重启后元数据可以恢复就需要把集群元数据持久化到磁盘 , 那需要规划 RabbitMQ 集群中的 RAM Node 和 Disc Node 。
只要有一个节点是 Disc Node 就能提供条件把集群元数据写到磁盘,RabbitMQ 的确也是这样要求的 : 集群中只要有一个 disk
node 就可以 , 其它的都可以是 RAM node. 节点加入或退出集群一定至少要通知集群中的一个 disk node 。
如果集群中 disk node 都宕掉 , 就不要变动集群的元数据 . 声明 exchange queue 修改用户权限 , 添加用户等等这些变动在节点重启之后无法恢复 。
有一种情况要求所有的 disk node 都要在线情况在才能操作 , 那就是增加或者移除节点
.RAM node 启动的时候会连接到预设的
disk node 下载最新的集群元数据 . 如果你有两个 disk node(d1 d2), 一个 RAM node 加入的时候你只告诉 d1, 而恰好这个 RAM node 重启的时候 d1 并没有启动 , 重启就会失败 . 所以加入 RAM 节点的时候 , 把所有的disk node 信息都告诉它 ,RAM node 会把 disk node 的信息持久化到磁盘以便后续启动可以按图索骥
8. RabbitMQ集群部署
1> 实验条件
1)3台主机192.168.16.65、66、68,配置好源。
屏蔽掉本地源即网络源,使用内网提供的源
[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# ls
bak local.repo Mariadb.repo net.repo
[root@localhost yum.repos.d]# mv local.repo local.repo.bak
[root@localhost yum.repos.d]# mv Mariadb.repo Mariadb.repo.bak
[root@localhost yum.repos.d]# mv net.repo net.repo.bak
[root@localhost yum.repos.d]# ls
bak local.repo.bak Mariadb.repo.bak net.repo.bak
[root@localhost ~]# rz
[root@localhost ~]# ls
anaconda-ks.cfg yum-repo.sh
更改网卡配置文件,修改DNS,使可以解析内网
[root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
BOOTPROTO=static
NAME=ens33
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.16.65
NETMASk=255.255.255.0
GATEWAY=192.168.16.2
DNS1=172.16.254.110
DSN2=114.114.114.114
[root@localhost ~]# systemctl restart network 查看域名解析文件
[root@localhost ~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 172.16.254.110
[root@localhost ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
:: localhost localhost.localdomain localhost6 localhost6.localdomain6 执行脚本,部署源
[root@localhost ~]# bash yum-repo.sh
[root@localhost ~]# cd /etc/yum.repos.d/
[root@localhost yum.repos.d]# ls
bak epel-yunwei.repo Mariadb.repo.bak old
Centos7-Base-yunwei.repo local.repo net.repo.bak
rdo-release-yunwei.repo
若无法解析主机,尝试进行域名解析,将解析文件写入/etc/resol.conf或/etc/hosts。
三台主机都进行DNS解析和源的配置。
2)三台主机能够静态解析彼此。
3)设置可以无秘钥登录。
[root@localhost ~]# ssh-keygen
[root@localhost ~]# ssh-copy-id 192.168.16.66
[root@localhost ~]# ssh-copy-id 192.168.16.68
[root@localhost ~]# ssh 192.168.16.66
[root@ajy6 ~]#exit
[root@localhost ~]# ssh 192.168.16.68
[root@ajy8 ~]#exit 为了区分各台主机,可以给各主机更改主机名
192.168.16.65:
[root@localhost ~]# hostnamectl set-hostname ajy5
[root@localhost ~]# hostname
ajy5 192.168.16.66:
[root@localhost ~]# hostname
ajy6 192.168.16.68:
[root@localhost ~]# hostnamectl set-hostname ajy8
[root@localhost ~]# hostname
ajy8 使用从快捷键Ctrl+D可以快速的退出登录回到本主机
2> 安装RabbitMQ
给所有的节点主机安装rabbitmq和erlang
[root@ajy5 ~]# yum install relang rabbitmq-server.noarch -y
[root@ajy6 ~]# yum install relang rabbitmq-server.noarch -y
[root@ajy8 ~]# yum install relang rabbitmq-server.noarch -y
3> 启动节点
[root@ajy5 ~]# systemctl enable rabbitmq-server.service
[root@ajy6 ~]# systemctl start rabbitmq-server.service
[root@ajy6 ~]# systemctl status rabbitmq-server.service
[root@ajy6 ~]# systemctl enable rabbitmq-server.service
[root@ajy6 ~]# systemctl start rabbitmq-server.service
[root@ajy6 ~]# systemctl status rabbitmq-server.service
[root@ajy8 ~]# systemctl enable rabbitmq-server.service
[root@ajy8 ~]# systemctl start rabbitmq-server.service
[root@ajy8 ~]# systemctl status rabbitmq-server.service
4> 查看监听的端口
rabbitmq-server监听端口为5672
[root@ajy8 ~]# netstat -lantp | grep
tcp6 ::: :::* LISTEN /beam
[root@ajy8 ~]# ss -tnl |grep
LISTEN ::: :::*
RabbitMQ的配置文件:/etc/rabbitmq/rabbitmq.config
5> 查看rabbitmq集群状态
[root@ajy5 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy5 ... #节点运行在ajy5服务上
[{nodes,[{disc,[rabbit@ajy5]}]}, #节点类型,单节点类型只允许disk
{running_nodes,[rabbit@ajy5]}, #运行结点
{cluster_name,<<"rabbit@ajy5">>},
{partitions,[]},
{alarms,[{rabbit@ajy5,[]}]}]
在没有将三个几点主机组成集群时,相当于三个集群。
[root@ajy6 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy6 ...
[{nodes,[{disc,[rabbit@ajy6]}]},
{running_nodes,[rabbit@ajy6]},
{cluster_name,<<"rabbit@ajy6">>},
{partitions,[]},
{alarms,[{rabbit@ajy6,[]}]}] [root@ajy8 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy8 ...
[{nodes,[{disc,[rabbit@ajy8]}]},
{running_nodes,[rabbit@ajy8]},
{cluster_name,<<"rabbit@ajy8">>},
{partitions,[]},
{alarms,[{rabbit@ajy8,[]}]}]
6> 将三个节点设置为一个集群
在ajy5上编辑环境变量配置文件
[root@ajy5 ~]# vim /etc/rabbitmq/rabbitmq-env.conf
RABBITMQ_NODE_PORT=
ulimit -S -n
RABBITMQ_SERVER_ERL_ARGS="+K true +A30 +P 1048576 -kernel inet_default_connect_options [{nodelay,true},{raw,6,18,<<5000:64/native>>}] -kernel inet_default_listen_options [{raw,6,18,<<5000:64/native>>}]"
RABBITMQ_NODE_IP_ADDRESS=192.168.16.65 #ip改为当前节点ip
将该配置文件发送给其他两个节点,并修改其他两个节点的ip。
[root@ajy5 ~]# scp /etc/rabbitmq/rabbitmq-env.conf 192.168.16.66:/etc/rabbitmq/
rabbitmq-env.conf % .3KB/s :
[root@ajy5 ~]# scp /etc/rabbitmq/rabbitmq-env.conf 192.168.16.68:/etc/rabbitmq/
rabbitmq-env.conf % .0KB/s :
[root@ajy6 ~]# vim /etc/rabbitmq/rabbitmq-env.conf
RABBITMQ_NODE_PORT=
ulimit -S -n
RABBITMQ_SERVER_ERL_ARGS="+K true +A30 +P 1048576 -kernel inet_default_connect_options [{nodelay,true},{raw,6,18,<<5000:64/native>>}] -kernel inet_default_listen_options [{raw,6,18,<<5000:64/native>>}]"
RABBITMQ_NODE_IP_ADDRESS=192.168.16.66
[root@ajy8 ~]# vim /etc/rabbitmq/rabbitmq-env.conf
RABBITMQ_NODE_PORT=
ulimit -S -n
RABBITMQ_SERVER_ERL_ARGS="+K true +A30 +P 1048576 -kernel inet_default_connect_options [{nodelay,true},{raw,6,18,<<5000:64/native>>}] -kernel inet_default_listen_options [{raw,6,18,<<5000:64/native>>}]"
RABBITMQ_NODE_IP_ADDRESS=192.168.16.68
查看rabbitmq插件
[root@ajy5 ~]# /usr/lib/rabbitmq/bin/rabbitmq-plugins list
Configured: E = explicitly enabled; e = implicitly enabled
| Status: [failed to contact rabbit@ajy5 - status not shown]
|/
[ ] amqp_client 3.6.
[ ] cowboy 1.0.
[ ] cowlib 1.0.
[ ] mochiweb 2.13.
[ ] rabbitmq_amqp1_0 3.6.
[ ] rabbitmq_auth_backend_ldap 3.6.
[ ] rabbitmq_auth_mechanism_ssl 3.6.
[ ] rabbitmq_consistent_hash_exchange 3.6.
[ ] rabbitmq_event_exchange 3.6.
[ ] rabbitmq_federation 3.6.
[ ] rabbitmq_federation_management 3.6.
[ ] rabbitmq_jms_topic_exchange 3.6.
[ ] rabbitmq_management 3.6. #web图形化界面
[ ] rabbitmq_management_agent 3.6.
[ ] rabbitmq_management_visualiser 3.6.
[ ] rabbitmq_mqtt 3.6.
[ ] rabbitmq_recent_history_exchange 1.2.
[ ] rabbitmq_sharding 0.1.
[ ] rabbitmq_shovel 3.6.
[ ] rabbitmq_shovel_management 3.6.
[ ] rabbitmq_stomp 3.6.
[ ] rabbitmq_top 3.6.
[ ] rabbitmq_tracing 3.6.
[ ] rabbitmq_trust_store 3.6.
[ ] rabbitmq_web_dispatch 3.6.
[ ] rabbitmq_web_stomp 3.6.
[ ] rabbitmq_web_stomp_examples 3.6.
[ ] sockjs 0.3.
[ ] webmachine 1.10.
所有节点开启rabbitmqweb插件
[root@ajy5 ~]# rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
mochiweb
webmachine
rabbitmq_web_dispatch
amqp_client
rabbitmq_management_agent
rabbitmq_management
Applying plugin configuration to rabbit@ajy5... started plugins.
重启rabbitmq-server服务
[root@ajy5 ~]# systemctl restart rabbitmq-server.service
[root@ajy6 ~]# systemctl restart rabbitmq-server.service
[root@ajy8 ~]# systemctl restart rabbitmq-server.service
再查看插件
[root@ajy5 ~]# /usr/lib/rabbitmq/bin/rabbitmq-plugins list
[E ] rabbitmq_management 3.6. #前面有个E表示启动
7> 通过web界面登录rabbitmq
rabbitmq的web端的端口为15672,访问时加上端口。输入用户名和密码,均为guest。
virtualhost用来对资源进行隔离。
rabbitmq manager的密码是可以修改的,使用命令rabbitmqctl。
[root@ajy5 ~]# rabbitmqctl change_password guest
Changing password for user "guest" ...
再用新密码登录。
8> 添加一个OpenStack用户
[root@ajy5 ~]# rabbitmqctl add_user openstack 123 #添加用户OpenStack,密码为123
Creating user "openstack" ...
设置权限,此处我给的是所有权限。
[root@ajy5 ~]# rabbitmqctl set_permissions openstack ".*" ".*" ".*"
Setting permissions for user "openstack" in vhost "/" ...
此时创建的OpenStack用户为普通用户,无法通过web界面进行登录,如要登录,需要将其改为administrator管理员进行登录。
[root@ajy5 ~]# rabbitmqctl set_user_tags openstack administrator
Setting tags for user "openstack" to [administrator] ...
9> 将ajy5的erlang.cookie到其他节点配置集群
[root@ajy5 ~]# cd /var/lib/rabbitmq/
[root@ajy5 ~]# cd /var/lib/rabbitmq/
[root@ajy5 rabbitmq]# ls -a
. .. .erlang.cookie mnesia
[root@ajy5 rabbitmq]# scp /var/lib/rabbitmq/.erlang.cookie 192.168.16.66:/var/lib/rabbitmq/.erlang.cookie
.erlang.cookie % .9KB/s :
[root@ajy5 rabbitmq]# scp /var/lib/rabbitmq/.erlang.cookie 192.168.16.68:/var/lib/rabbitmq/.erlang.cookie
重启两个节点的主服务,停止ajy6和ajy8节点的app应用。
[root@ajy6 ~]# systemctl restart rabbitmq-server.service
[root@ajy6 ~]# rabbitmqctl stop_app
Stopping node rabbit@ajy6 ...
两节点停止应用后加入集群,以ram类型加入节点ajy5。
注意,此处使用节点为主机名,因此要先进行域名解析。
[root@ajy5 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
:: localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.16.65 ajy5
192.168.16.66 ajy6
192.168.16.68 ajy8
[root@ajy5 ~]# scp /etc/hosts 192.168.16.66:/etc/hosts
hosts % .5KB/s :
[root@ajy5 ~]# scp /etc/hosts 192.168.16.68:/etc/hosts
hosts % .5KB/s :
两个节点ajy6、ajy8加入节点ajy5
[root@ajy6 ~]# rabbitmqctl join_cluster --ram rabbit@ajy5
Clustering node rabbit@ajy6 with rabbit@ajy5 ...
[root@ajy8 ~]# rabbitmqctl join_cluster --ram rabbit@ajy5
Clustering node rabbit@ajy6 with rabbit@ajy5 ...
加入之后再启动两节点的app应用。
[root@ajy6 ~]# rabbitmqctl start_app
Starting node rabbit@ajy6 ...
[root@ajy8 ~]# rabbitmqctl start_app
Starting node rabbit@ajy8 ...
查看节点ajy5的集群状态
[root@ajy5 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy5 ...
[{nodes,[{disc,[rabbit@ajy5]},{ram,[rabbit@ajy8,rabbit@ajy6]}]},
{running_nodes,[rabbit@ajy6,rabbit@ajy5]},
{cluster_name,<<"rabbit@ajy5">>},
{partitions,[]},
{alarms,[{rabbit@ajy6,[nodedown]},{rabbit@ajy5,[]}]}]
在web端查看
10> 更改节点类型
将ajy6的节点类型改为disk类型,
[root@ajy6 ~]# rabbitmqctl stop_app
Stopping node rabbit@ajy6 ...
[root@ajy6 ~]# rabbitmqctl change_cluster_node_type disk
Turning rabbit@ajy6 into a disc node ...
[root@ajy6 ~]# rabbitmqctl start_app
Starting node rabbit@ajy6 ...
[root@ajy6 ~]# rabbitmqctl stop_app
Stopping node rabbit@ajy6 ...
[root@ajy6 ~]# rabbitmqctl change_cluster_node_type ram
Turning rabbit@ajy6 into a ram node ...
[root@ajy6 ~]# rabbitmqctl start_app
Starting node rabbit@ajy6 ...
[root@ajy6 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy6 ...
[{nodes,[{disc,[rabbit@ajy5]},{ram,[rabbit@ajy8,rabbit@ajy6]}]},
{running_nodes,[rabbit@ajy5,rabbit@ajy6]},
{cluster_name,<<"rabbit@ajy5">>},
{partitions,[]},
{alarms,[{rabbit@ajy5,[]},{rabbit@ajy6,[]}]}]
11> 从集群中移除(重置)节点
移除节点ajy8
[root@ajy8 ~]# rabbitmqctl stop_app
Stopping node rabbit@ajy8 ...
[root@ajy8 ~]# rabbitmqctl reset
Resetting node rabbit@ajy8 ...
[root@ajy8 ~]# rabbitmqctl start_app
Starting node rabbit@ajy8 ...
[root@ajy8 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy8 ...
[{nodes,[{disc,[rabbit@ajy8]}]}, #只有一个节点
{running_nodes,[rabbit@ajy8]},
{cluster_name,<<"rabbit@ajy8">>},
{partitions,[]},
{alarms,[{rabbit@ajy8,[]}]}]
[root@ajy5 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy5 ...
[{nodes,[{disc,[rabbit@ajy5]},{ram,[rabbit@ajy6]}]}, #只有两个节点
{running_nodes,[rabbit@ajy6,rabbit@ajy5]},
{cluster_name,<<"rabbit@ajy5">>},
{partitions,[]},
{alarms,[{rabbit@ajy6,[nodedown]},{rabbit@ajy5,[]}]}]
12> 从某个节点上移除集群中的其他节点
在ajy5上移除ajy6节点
先关掉节点
[root@ajy6 ~]# rabbitmqctl stop_app
Stopping node rabbit@ajy6 ... 再进行移除
[root@ajy5 ~]# rabbitmqctl forget_cluster_node rabbit@ajy6
Removing node rabbit@ajy6 from cluster ... 查看
[root@ajy5 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@ajy5 ...
[{nodes,[{disc,[rabbit@ajy5]}]},
{running_nodes,[rabbit@ajy5]},
{cluster_name,<<"rabbit@ajy5">>},
{partitions,[]},
{alarms,[{rabbit@ajy5,[]}]}]
注意:
1> 保证集群中至少有一个磁盘类型的节点以防数据丢失,在更改节点类型时尤其要注意。
2> 若整个集群被停掉了,应保证最后一个 down 掉的节点被最先启动,若不能则要使用 forget_cluster_node 命令将其移出集群。
3> 若集群中节点几乎同时以不可控的方式 down 了,此时在其中一个节点使用 force_boot 命令重启节点。
OpenStack共享组件-RabbitMQ消息队列的更多相关文章
- openstack共享组件--rabbitmq消息队列(1)
一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们. 消息传 ...
- OpenStack组件——RabbitMQ消息队列
1.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们. 消息传 ...
- openstack (共享服务) 消息队列rabbitmq服务
云计算openstack共享组件——消息队列rabbitmq(3) 一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队 ...
- 使用EasyNetQ组件操作RabbitMQ消息队列服务
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现,是实现消息队列应用的一个中间件,消息队列中间件是分布式系统中重要的组件,主要解决应用耦合, ...
- OpenStack共享组件
一.云计算的前世今生 1.物理机架构,应用部署和运行在物理机上 2.虚拟化架构,物理机上运行若干虚拟机,应用系统直接部署到虚拟机上 3.云计算架构,虚拟化提高了单台物理机的资源使用率 二.Open ...
- RabbitMQ消息队列(一): Detailed Introduction 详细介绍
http://blog.csdn.net/anzhsoft/article/details/19563091 RabbitMQ消息队列(一): Detailed Introduction 详细介绍 ...
- RabbitMQ消息队列1: Detailed Introduction 详细介绍
1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...
- (转)RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...
- RabbitMQ消息队列应用
RabbitMQ消息队列应用 消息通信组件Net分布式系统的核心中间件之一,应用与系统高并发,各个组件之间解耦的依赖的场景.本框架采用消息队列中间件主要应用于两方面:一是解决部分高并发的业务处理:二是 ...
随机推荐
- 导出excel按照指定格式
1.项目有个需求,要按照特定格式 导出Excel表格. 正常的都是一行 ,下面是数据.这次有个变动,就是每隔 几列要换行,下面是数据.在下面是数据部分.花了一上午写了下需求,不难但是花时间 //实现特 ...
- phpspreadsheet 中文文档(七)技巧和诀窍
2019年10月11日14:08:35 以下页面为您提供了一些使用广泛的PhpSpreadsheet食谱.请注意,这些文件没有提供有关特定PhpSpreadsheet API函数的完整文档,而只是一个 ...
- JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API.
JobStorage.Current property value has not been initialized. You must set it before using Hangfire Cl ...
- Consumer clientId=consumer-1, groupId=console-consumer-950] Connection to node -1 could not be
kafka创建主题的ip地址最好用实际ip,不要用localhost https://blog.csdn.net/getyouwant/article/details/79000524
- Java中的常量池(字符串常量池、class常量池和运行时常量池)
转载. https://blog.csdn.net/zm13007310400/article/details/77534349 简介: 这几天在看Java虚拟机方面的知识时,看到了有几种不同常量池的 ...
- LeetCode 1223. 掷骰子模拟 Dice Roll Simulation - Java - DP
题目链接:1223. 掷骰子模拟 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[ ...
- JAVA知识点总结篇(三)
抽象类 使用规则 abstract定义抽象类: abstract定义抽象方法,只有声明,不需要实现: 包含抽象方法的类是抽象类: 抽象类中可以包含普通方法,也可以没有抽象方法: 抽象类不能直接创建,可 ...
- *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
Warning提示的原因是 一些未使用的函数被编译进入芯片,浪费了RAM/ROM. 解决的方法: 1.将不用的函数注释: 2.在未使用函数的首尾加条件编译 #ifdef 函数名 和 #endif ,不 ...
- sublime text 打开总是弹框报错Unable to download ChineseLocalizations. Please view the console for more details.解决办法
本文链接:https://blog.csdn.net/qq_36435508/article/details/92805256 依次点击软件的 Preferences->Package S ...
- go 学习笔记 ----资源自动回收
在释放局部资源时, 可以用defer管理 Go语言版本基于defer的Mutex用法 func safeRead(Mutex *mu) []byte { mu.Lock() defer mu.Unlo ...