一、什么是消息队列
简单通俗讲生产者产生一个消息发送到队列中,队列负责存放消息,消费者从队列中拉取消息。生产者只管发送消息,消费者只管接收消息。
二、为什么使用消息队列
其实就是在生产环境中的应用场景。核心就三个:解耦、异步、削峰。
- 解耦:列如接口调用,A,B,C,D四个接口,BCD调用A接口,此时新增加E接口,去调用A接口,此时某一个接口不使用了A怎么办?如果同时其他BCDE接口down掉,怎么处理?此时引入MQ,A产生数据发送到MQ队列中,其他接口只需要从队列中拉取就行,不需要考虑拉取失败,超时等。
- 异步:A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、350ms、200ms。最终请求总延时是 3 + 300 + 350 + 200 = 853ms,接近 1s,用户体验太差了。使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了。
- 削峰:列如双十一秒杀,春运火车票抢购,消息中间件采用队列的形式可以减少突发访问压力,把请求的流量转义到其他服务器上.
三、RabbitMQ特点 - 可靠性(Reliability)
- 灵活的路由(Flexible Routing)
- 消息集群(Clustering)
- 高可用(Highly Available Queues)
- 多种协议(Multi-protocol)
- RabbitMQ 几乎支持所有常用语言比如 Java、.NET、Ruby 等等。
- 管理界面(Management UI)
- 跟踪机制(Tracing)
- 插件机制(Plugin System)
四、RabbitMQ模型
-
消息模型
所有MQ产品从模型抽象上来说都是一样的过程 消费者(consumer)订阅某个队列。生产者(producer)创建消息,然后发布到队列(queue)中,最后将消息发送带监听的消费者。
2.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 表示消息队列服务器实体。
五、RabbitMQ集群
RabbitMQ 最优秀的功能之一就是内建集群,这个功能设计的目的是允许消费者和生产者在节点崩溃的情况下继续运行,以及通过添加更多的节点来线性扩展消息通信吞吐量。RabbitMQ 内部利用 Erlang 提供的分布式通信框架 OTP 来满足上述需求,使客户端在失去一个 RabbitMQ 节点连接的情况下,还是能够重新连接到集群中的任何其他节点继续生产、消费消息。
- A、RabbitMQ集群中的一些概念
RabbitMQ 会始终记录以下四种类型的内部元数据:- 队列元数据 :包括队列名称和它们的属性,比如是否可持久化,是否自动删除
- 交换器元数据 :交换器名称、类型、属性
- 绑定元数据:内部是一张表格记录如何将消息路由到队列
- vhost 元数据 :为 vhost 内部的队列、交换器、绑定提供命名空间和安全属性
- 集群架构
B、RabbitMQ环境搭建
-
5.1、
每个主机部署rabbitMQ(这里我采用ansible方便快捷) 安装Erlang 配置yum源 vim
/etc/yum.repos.d/rabbitmq_erlang.repo
[root@master ansible]# ansible websql -m copy -a “src=/etc/yum.repos.d/rabbitmq_erlang.repo dest=/etc/yum.repos.d/ mode=755 owner=root”
安装
[root@master ansible]# ansible websql -m yum -a “name=erlang state=installed”
验证:
[root@master ansible]# ansible websql -m shell -a " erl -version"
安装RabbitMQ
配置源
[root@master ~]# ansible websql -m shell -a “curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | sudo bash”
安装:
[root@master ~]# ansible websql -m yum -a “name=rabbitmq-server state=installed”
查看RabbitMQ安装目录
[root@master ~]# ansible websql -m shell -a “whereis rabbitmq”
启动服务:systemctl start rabbitmq-server
停止服务:systemctl stop rabbitmq-server
运行状态:systemctl status rabbitmq-server
重启:systemctl restart rabbitmq-server
[root@master ~]# ansible websql -m shell -a “systemctl start rabbitmq-server”
[root@master ~]# ansible websql -m shell -a “systemctl status rabbitmq-server”
查看端口号:
[root@master ~]# ansible websql -m shell -a “netstat -lnt | grep 5672”
设置开机自启动:
[root@master ~]# ansible websql -m shell -a “chkconfig rabbitmq-server on”
安装WEB UI界面
需要启动插件管理
[root@master ~]# ansible websql -m shell -a “rabbitmq-plugins enable rabbitmq_management”
新增账号,用户名root 密码000000
[root@master ~]# ansible websql -m shell -a “rabbitmqctl add_user root 000000”
赋予用户在默认的名为/下的Virtual Host的所有权限
[root@master ~]# ansible websql -m shell -a “rabbitmqctl set_permissions -p / root ‘.’ '.’ ‘.’"
设置用户角色为管理员
[root@master ~]# ansible websql -m shell -a “rabbitmqctl set_user_tags root administrator”
登陆可以看见MQ个Erl的版本号,以及对应用户信息
解锁linux系统最大进程数和最大文件打开数
[root@master ~]#ansible websql -m shell -a "echo ’ soft nofile 655350’ >> /etc/security/limits.conf”
[root@master ~]# ansible websql -m shell -a “echo ‘* soft nproc 655350’ >> /etc/security/limits.conf”
[root@master ~]# ansible websql -m shell -a “sysctl -p”
-
5.2、开启集群
配置Erlang Cookie
将 rabbit-node1 上的 .erlang.cookie 文件拷贝到其他两台主机上。该 cookie 文件相当 于密钥令牌,集群中的 RabbitMQ 节点需要通过交换密钥令牌以获得相互认证,因 此处于同一集群的所有节点需要具有相同的密钥令牌,否则在搭建过程中会出 现 Authentication Fail 错误。
RabbitMQ 服务启动时,erlang VM 会自动创建该 cookie 文件,默认的存储路径 为 /var/lib/rabbitmq/.erlang.cookie 或 $HOME/.erlang.cookie,该文件是一个隐藏文 件,需要使用 ls -al 命令查看。(拷贝.cookie时,各节点都必须停止MQ服务):
[root@master ~]# ansible websql -m shell -a “systemctl stop rabbitmq-server”
[root@master ~]# ansible websql -m copy -a “src=/var/lib/rabbitmq/.erlang.cookie dest=/var/lib/rabbitmq/”
修改权限
[root@master ~]# ansible websql -m shell -a “chmod 600 /var/lib/rabbitmq/.erlang.cookie”
启动服务:
[root@master ~]# ansible websql -m shell -a “systemctl start rabbitmq-server”
RabbitMQ 集群的搭建需要选择其中任意一个节点为基准,将其它节点逐步加入。 这里我们以 rabbit-master 为基准节点,将 rabbit-salve1 和 rabbit-slave2 加入集群。 在 rabbit-salve1 和rabbit-slave2 上执行以下命令
停止服务rabbitmqctl stop_app
重置状态rabbitmqctl reset
节点加入,在一个node加入cluster之前,必须停掉改node的rabbitmq应用,即 先执行rabbitmqctl join_cluster rabbit@master
启动服务rabbitmqctl start_app
查看集群状态
此时搭建成功,网页验证
配置镜像队列
开启镜像队列
语法如下:
[root@master ~]# rabbitmqctl set_policy ha-all “^” ‘{“ha-mode”:“all”}’
复制系数:
在上面我们指定了 ha-mode 的值为 all ,代表消息会被同步到所有节点的相同队列中。这里我们之所以这样配置,因为我们本身只有三个节点,因此复制操作的性能开销比较小。如果你的集群有很多节点,那么此时复制的性能开销就比较大,此时需要选择合适的复制系数。通常可以遵循过半写原则,即对于一个节点数为 n 的集群,只需要同步到 n/2+1 个节点上即可。此时需要同时修改镜像策略为 exactly,并指定复制系数 ha-params,示例命令如下:
rabbitmqctl set_policy ha-two “^” ‘{“ha-mode”:“exactly”,“ha-params”:2,“ha-sync-mode”:“automatic”}’
除此之外,RabbitMQ 还支持使用正则表达式来过滤需要进行镜像操作的队列,示例如下:
rabbitmqctl set_policy ha-all “^ha.” ‘{“ha-mode”:“all”}’
WEB UI 查看:
-
5.3、HAProxy环境搭建
wget https://www.haproxy.org/download/2.4/src/haproxy-2.4.8.tar.gz
tar -zxvf haproxy-2.4.8.tar.gz
编译安装并配置环境
make TARGET=linux-glibc PREFIX=/usr/local/haproxy-2.4.8
make install PREFIX=/usr/local/haproxy-2.4.8vim /etc/profile
export HAPROXY_HOME=/usr/local/haproxy-2.4.8
export PATH= P A T H : PATH: PATH:HAPROXY_HOME/sbin
source /etc/profile验证是否安装成功
haproxy -v
负载均衡配置
mkdir -p /etc/haproxy
vim /etc/haproxy/haproxy.cfg全局配置
global
# 日志输出配置、所有日志都记录在本机,通过 local0 进行输出
log 127.0.0.1 local0 info
# 最大连接数
maxconn 4096
# 改变当前的工作目录
chroot /usr/local/haproxy-2.1.8
# 以指定的 UID 运行 haproxy 进程
uid 99
# 以指定的 GID 运行 haproxy 进程
gid 99
# 以守护进行的方式运行
daemon
# 当前进程的 pid 文件存放位置全局配置
global
# 日志输出配置、所有日志都记录在本机,通过 local0 进行输出
log 127.0.0.1 local0 info
# 最大连接数
maxconn 4096
# 改变当前的工作目录
chroot /usr/local/haproxy-2.4.8
# 以指定的 UID 运行 haproxy 进程
uid 99
# 以指定的 GID 运行 haproxy 进程
gid 99
# 以守护进行的方式运行
daemon
# 当前进程的 pid 文件存放位置
pidfile /usr/local/haproxy-2.4.8/haproxy.pid默认配置
defaults
# 应用全局的日志配置
log global
# 使用4层代理模式,7层代理模式则为"http"
mode tcp
# 日志类别
option tcplog
# 不记录健康检查的日志信息
option dontlognull
# 3次失败则认为服务不可用
retries 3
# 每个进程可用的最大连接数
maxconn 2000
# 连接超时
timeout connect 5s
# 客户端超时
timeout client 120s
# 服务端超时
timeout server 120s绑定配置
listen rabbitmq_cluster
bind :5671
# 配置TCP模式
mode tcp
# 采用加权轮询的机制进行负载均衡
balance roundrobin
# RabbitMQ 集群节点配置
server mq-master master:5672 check inter 5000 rise 2 fall 3 weight 1
server mq-slave1 slave1:5672 check inter 5000 rise 2 fall 3 weight 1
server mq-slave2 slave2:5672 check inter 5000 rise 2 fall 3 weight 1配置监控页面
listen monitor
bind :8100
mode http
option httplog
stats enable
stats uri /stats
stats refresh 5s负载均衡的主要配置在 listen rabbitmq_cluster 下,这里指定负载均衡的方式为加权轮询,同时定义好健康检查机制:
启动服务:
haproxy -f /etc/haproxy/haproxy.cfg
查看运行:
ps aux|grep haproxy
WEB UI界面查看:
http://192.168.254.240:8100/stats
所有节点都为绿色,代表节点健康。此时证明 HAProxy 搭建成功,并已经 对 RabbitMQ 集群进行监控。
-
5.4、keepalived安装
yum -y install keepalived
配置keepalived.conf
master:
[root@master ~]# cat /etc/keepalived/keepalived.conf! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id master vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_scripts chk_haproxy{ script "/etc/keepalived/haproxy_check.sh" interval 5 weight 10 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 unicast_src_ip 192.168.254.240 unicast_peer { 192.168.254.241 } authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.254.200 } track_script { chk_haproxy } } Slave1: [root@slave1 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id master vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_scripts chk_haproxy{ script "/etc/keepalived/haproxy_check.sh" interval 5 weight 10 } vrrp_instance VI_1 { state backup interface ens33 virtual_router_id 51 priority 90 advert_int 1 unicast_src_ip 192.168.254.241 unicast_peer { 192.168.254.240 } authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.254.200 } track_script { chk_haproxy } }
##注意 state角色一个为主一个为备 priority:主的要比备的大 Interface 为网卡ID 使用ip addr list查看 配置haproxy监控脚本(master,slave1)
#!/bin/bash #判断haproxy是否启动 if [ ${ps -C haproxy --no-header |wc -l} -eq 0 ];then #如果没有启动就启动 haproxy -f /etc/haproxy/haproxy.cfg fi sleep 3 #如果haproxy启动不起来,将当前的keepalived停掉,虚拟IP漂浮到另外一台haproxy if [ ${ps -C haproxy --no-header | wc -l} -eq -0];then systemctl stop keepalived fi
授予权限chmod o+x haproxy_check.sh
开启ipv4转发
echo “net.ipv4.ip_nonlocal_bind = 1” >> /etc/sysctl.conf
sysctl -p
开启keepalived,并设置开机自启动
systemctl start keepalived
systemctl enable keepalived
验证:
搭建完成!!!
后续出一个:kafka与zookeeper
关注博主不迷路!博主带你上高速!