先说说安装rabbit的坑
1),由于rabbit是依赖erlang开发包的,所以小编一开始安装的erlang是centOs6机器上的,小编安装的rabbitmq是rabbitmq-server-3.7.9这个版本,导致在安装的时候 由于erlang版本太低 安装的时候总是报 >= 19.3 的错误,这里记录一下踩过的坑
首先,我们卸载掉旧版本的erlang
命令:
yum list | grep erlang
yum remove erlang*
在这个地址下载erlang的rpm安装包 https://bintray.com/rabbitmq/rpm/erlang/20.3-1
在这里下载rabbitMq的安装包,选好自己的服务器系统对应的版本 http://www.rabbitmq.com/install-rpm.html
两个依赖包下载好以后我们通过文件传输工具传输到我们的服务器当中 保存在/usr/local/RabbitMq 目录当中
a),yum clean all
b),yum makecache
c),rpm -ivh erlang-20.3-1.el7.centos.x86_64.rpm
d),yum localinstall erlang-20.3-1.el7.centos.x86_64.rpm (这个命令 是让yum从本地的rpm包安装)
e),rpm -ivh rabbitmq-server-3.7.9-1.el7.noarch.rpm
看到这个画面 说明rabbitMq安装成功
启动rabbitmq
systemctl start rabbitmq-server.service
查看rabbitmq状态
rabbitmqctl status
启用管理插件
rabbitmq-plugins enable rabbitmq_management
重启服务
systemctl restart rabbitmq-server.service
添加用户 用户名:wanglong 密码:passwd
rabbitmqctl add_user wanglong passwd
赋予wanglong administrator权限
rabbitmqctl set_user_tags wanglong administrator
设置权限
rabbitmqctl set_permissions -p / wanglong “." ".” “.*”
如果不加权限 那么上图中划线的部分会显示 no access 那么我们在项目当中连接启动时会报错
开启防火墙
systemctl enable firewalld
开机禁用防火墙
systemctl disable firewalld
查看防火墙状态
systemctl status firewalld
** 开放端口**
firewall-cmd --add-port=15672/tcp --permanent
firewall-cmd --reload
rabbitmq常用命令
add_user
delete_user
change_password
list_users
add_vhost
delete_vhost
list_vhostsset_permissions [-p ]
clear_permissions [-p ]
list_permissions [-p ]
list_user_permissions
list_queues [-p ] [ …]
list_exchanges [-p ] [ …]
list_bindings [-p ]
list_connections [ …]
浏览器访问 http://ip:15672 ,进入如下页面就证明插件启动成功了。
如果我们启动报错(com.rabbitmq.client.ShutdownSignalException:)
则我们打开安装rabbit的服务器
cd /etc/rabbitmq
vim rabbitmq.config
写下如下内容
[{rabbit, [{loopback_users, []}]}].
此配置的意为用户开放权限,进行外网访问
下面,我们先写测试代码 分别写一个sender 和 reveiver
接下来,我们先运行sender
此时我们可以打开我们的管理工具查看一下
我们可以看到此时服务器中存在一个名为hello的队列 并且产生了一条消息,然后 我们运行一下receiver
此时管理工具中名为hello的队列里已经没有消息了(被消费了)
接下来,我们整合进 springboot项目当中,以及参数配置
1),pom依赖
2),便于规范,再配置文件当中我们通过@bean注入所需要的消息队列 并给队列取名
3),新建一个message包 代表我们的消息部分 同时创建我们的消息生产者和消息消费者
@RabbitListener注解表示一个消息监听器,并制定queue参数,此监听器回去监听该队列中的消息,@RabbitHandler注解为我们接收到消息的处理函数,为了测试发送,我们写一个Rest接口来模拟我们的消费者发送消息
另外,由于小编在这个项目里加了用户认证授权,如果访问该接口,由于不提供token的话,会跳转到登陆页面去登陆,为了省略掉此操作,我们把配置文件改写一下,把此接口路径放开
准备工作做好以后 我们debug项目
访问接口,同时进行断点测试
我们可以看到,发送了消息之后,会被立马监听捕捉并消费掉
我们把断点执行完
会看到,队列中已经没有了消息,通过点对点模式 我们发现,如果不消费消息,那么如果消费者一直发送,消息会存在队列里面,直到消费者消费(且消费的顺序是按照发送者的顺序),当然 我们发送的消息也可以是对象,注意这里会存在序列化和反序列化的问题,我们只需让改对象实现 序列化接口即可
RabbitMQ添加用户和Virtual Host
Admin-Users-Add a user
Tags:用户角色说明
超级管理员(administrator)
可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
监控者(monitoring)
可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
策略制定者(policymaker)
可登陆管理控制台, 同时可以对policy进行管理,但无法查看节点的相关信息。
普通管理者(management)
仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
其他none
无法登陆管理控制台,通常就是普通的生产者和消费者。
Admin-Virtual Host-Add virtual host
添加virtual host和用户后,需要为用户指定virtual host,之后用该用户可以登录
RabbitMq基础知识
摘录自 https://www.cnblogs.com/dwlsxj/p/RabbitMQ.html
小编画了一个整体的结构图,介绍了发送消息和接收消息的大体流程
Queue
Queue在队列存储消息,由于它先进先出的特性,生产者生产的消息将会被放到queue当中去,而消费者则是从queue中取出对象,
生产者 生产的A消息会被传送到Queue当中去,消费者发现队列中订阅的有这条消息 会把这条消息取出来 进行业务操作,这是一个消费者对应一个queue的情况,也可以多个消费者订阅多个queue的情况,就会将queue的消息 平分给其他消费者,但是如果每个消息处理时间不同,就会导致有些消费者一直处于忙碌中,而有些消费者由于消费了消息 处于空闲状态,可以用prefetchcount来限制每次发送给消费者消息的个数
prefechCount = 1的意思是每次从queue中消费一条消息来,等消费者处理完这条消息后,queue会再发送一条消息给消费者
Exchange
在上面的构造图中 clientA 和 clientB 如何知道消息要发送到哪个queue当中去呢,然而消息并不是直接发送到queue当中去的 而是要经过exchange,由exchange将消息路由到一个或多个queue当中去,这里有 exchangeType这个属性,而exchange怎样准确定位哪个具体的queue呢?在rabbitmq当中,通过Binding把exchange和queue连接起来,这样exchange就知道具体推送个哪个具体的queue了
在绑定(Binding)Exchange和Queue的同时,会指定一个bindingkey,生产者将消息发送给Exchange的时候,会产生一个RoutingKey 如果Binding key 和对应上时,消息就会发送到对应的queue中去,Exchange有四种类型,不同类型有着不同的策略,也就是不同的类型会绑定到不同的queue当中。换言之就是说生产者发送了一个消息,Routing Key的规则是A,那么生产者会将Routing Key=A的消息推送到Exchange中,这时候Exchange中会有自己的规则,对应的规则去筛选生产者发来的消息,如果能够对应上Exchange的内部规则就将消息推送到对应的Queue中去。那么接下来就来详细讲解下Exchange里面类型。
Exchange type
1,fanout
fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。
2,direct
direct类型的 Exchange路由规则很简单,它会将消息发送到Routing和Bindingkey完全匹配的queue当中去
当生产者(P)发送消息时Rotuing key=booking时,这时候将消息传送给Exchange,Exchange获取到生产者发送过来消息后,会根据自身的规则进行与匹配相应的Queue,这时发现Queue1和Queue2都符合,就会将消息传送给这两个队列,如果我们以Rotuing key=create和Rotuing key=confirm发送消息时,这时消息只会被推送到Queue2队列中,其他Routing Key的消息将会被丢弃。
topic
上面两种的 direct模式是严格意义上的匹配,换言之Routing Key必须与Binding Key相匹配的时候才将消息传送给Queue,那么topic这个规则就是模糊匹配,可以通过通配符满足一部分规则就可以传送。它的约定是:
当生产者发送消息Routing Key=F.C.E的时候,这时候只满足Queue1,所以会被路由到Queue中,如果Routing Key=A.C.E这时候会被同是路由到Queue1和Queue2中,如果Routing Key=A.F.B时,这里只会发送一条消息到Queue2中。
ConnectionFactory、Connection、Channel
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。
Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
Connection就是建立一个TCP连接,生产者和消费者的都是通过TCP的连接到RabbitMQ Server中的,这个后续会再程序中体现出来。
Channel虚拟连接,建立在上面TCP连接的基础上,数据流动都是通过Channel来进行的。为什么不是直接建立在TCP的基础上进行数据流动呢?如果建立在TCP的基础上进行数据流动,建立和关闭TCP连接有代价。频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。
下面,我们接着改程序,使用 Exchange type 为topic 类型
接着 我们 分别写两个消费者
我们在生产者中增加方法
启动并开启断点调试
我们会看到,生产者往topic.quque1队列中发送消息,分别在quque1队列和queue2队列上监听的消费者同时接收到了消息,原因是因为我们在配置中为queue2队列与交换机绑定的时候 routingKey设置的为topic.*,因此也会模糊匹配到queue2队列,如果我们将此routingKey改为topic.queue2 那么就只有quque1会接收到发送的消息
接下来,我们再改写上面的程序 改为fanout模式
生产者中添加方法 这里我们忽略掉第二个参数