搭建高可用/高可靠的RabbitMQ镜像队列集群架构

RabbitMQ镜像队列模式集群:

  • RabbitMQ集群模式非常经典的就是Mirror镜像模式,节点足够的情况下能保证100%数据不丢失,在实际工作中也是用的最多的。并且实现集群非常的简单,一般互联网大厂都会构建这种镜像集群模式
  • Mirror镜像队列,目的是为了保证rabbitmq数据的高可靠性解决方案,主要就是实现数据的同步,一般来讲是2-3个节点实现数据同步(对于100%数据可靠性解决方案一般是3节点以上)

在本文中将要搭建的RabbitMQ集群架构如下:


image.png

RabbitMQ集群环境节点说明:

机器IP hostname 节点说明 端口 管控台地址
192.168.243.164 rabbitmq01 RabbitMQ Master 5672 http://192.168.243.164:15672
192.168.243.165 rabbitmq02 RabbitMQ Slave 5672 http://192.168.243.165:15672
192.168.243.166 rabbitmq03 RabbitMQ Slave 5672 http://192.168.243.166:15672
192.168.243.167 haproxy01 HAProxy + Keepalived 8100 http://192.168.243.167:8100/rabbitmq-stats
192.168.243.168 haproxy02 HAProxy + Keepalived 8100 http://192.168.243.168:8100/rabbitmq-stats

192.168.243.164、192.168.243.165及192.168.243.166这三台机器上需要事先安装好RabbitMQ,具体安装步骤参考如下文章:

这三台机器的hosts文件均需配置IP与hostname的映射关系,如下:

$ cat /etc/hosts
192.168.243.164 rabbitmq01
192.168.243.165 rabbitmq02
192.168.243.166 rabbitmq03

接下来我们将这三台RabbitMQ节点组成镜像队列集群。首先,需要将这三个节点的RabbitMQ服务都停止,如果启动了的话:

$ rabbitmqctl stop_app

这里我将192.168.243.164这个节点作为Master角色,把Master节点的.erlang.cookie文件拷贝到其他两台机器上:

[root@rabbitmq01 ~]# scp /var/lib/rabbitmq/.erlang.cookie 192.168.243.165:/var/lib/rabbitmq/
[root@rabbitmq01 ~]# scp /var/lib/rabbitmq/.erlang.cookie 192.168.243.166:/var/lib/rabbitmq/

然后分别在三个节点上执行如下命令,配置为独立模式:

$ rabbitmq-server -detached

启动master节点:

[root@rabbitmq01 ~]# rabbitmqctl start_app

将salve加入到集群中:

[root@rabbitmq02 ~]# rabbitmqctl join_cluster rabbit@rabbitmq01
Clustering node rabbit@rabbitmq02 with rabbit@rabbitmq01
[root@rabbitmq02 ~]# rabbitmqctl start_app

[root@rabbitmq03 ~]# rabbitmqctl join_cluster rabbit@rabbitmq01
Clustering node rabbit@rabbitmq03 with rabbit@rabbitmq01
[root@rabbitmq03 ~]# rabbitmqctl start_app
  • Tips:如果想让加入集群中的节点是以内存方式存储数据,则需要加上--ram参数,否则默认是磁盘存储

完成以上步骤后,此时集群就已经搭建起来了,可以使用如下命令查看集群状态信息:

[root@rabbitmq01 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq01 ...
Basics

Cluster name: rabbit@rabbitmq01

Disk Nodes

rabbit@rabbitmq01
rabbit@rabbitmq02
rabbit@rabbitmq03

Running Nodes

rabbit@rabbitmq01
rabbit@rabbitmq02
rabbit@rabbitmq03

...

我们可以使用如下命令修改集群名称(默认为第一个节点的名称):

[root@rabbitmq01 ~]# rabbitmqctl set_cluster_name dev_rabbitmq_cluster
Setting cluster name to dev_rabbitmq_cluster ...
[root@rabbitmq01 ~]# 

如果以后需要移除集群中的节点可以在master节点上使用如下命令:

$ rabbitmqctl forget_cluster_node rabbit@rabbitmq02

使用浏览器访问集群中任意一个节点的管控台,在“Nodes”一栏中可以看到列出了集群中所有节点的概览信息:


image.png

经过以上步骤搭建好普通集群后,此时集群中的节点还是会各自存储各自的数据,数据不会在多个节点中冗余存储,这样其中一个节点挂掉了,那么该节点的数据就无法被消费了。

所以接下来我们还需要配置集群模式为镜像队列模式,将所有队列设置为镜像队列后,队列才会被复制到各个节点上,让各个节点状态保持一致。设置镜像队列策略的命令如下(在任意一个节点上执行):

[root@rabbitmq01 ~]# rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
Setting policy "ha-all" for pattern "^" to "{"ha-mode":"all"}" with priority "0" for vhost "/" ...
[root@rabbitmq01 ~]# 

然后到任意一个节点的管控台上创建一个队列:


image.png

此时可以发现其他节点也会复制该队列,代表镜像队列模式配置成功:


image.png

RabbitMQ集群整合负载均衡基础组件HAProxy

在上一小节中,我们搭建了RabbitMQ的镜像队列集群,虽然集群节点之间能够同步数据保证高可靠的存储了,但有个问题就是客户端通常只能连接集群中的其中一个节点。这样就会造成集群中只有一个节点在负载所有的读写操作,导致该节点负载过高,而其他节点则无所事事。

因此,我们就需要对RabbitMQ集群做负载均衡,负载均衡的方案通常有服务端负载均衡和客户端负载均衡两种。客户端负载均衡需要我们自己在客户端实现负载均衡算法,或使用第三方的库。服务端负载均衡则是通过一些中间件来实现,例如HAProxy、Nginx、LVS等。

由于本文主要是演示环境的搭建不涉及编码,所以采用的是服务端负载均衡方案,使用HAProxy组件来做RabbitMQ集群的负载均衡组件。

HAProxy是一款提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。 HAProxy特别适用于那些负载特大的web站点。这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进你当前的架构中,同时可以保护你的web服务器不被暴露到网络上。

HAProxy借助于OS上几种常见的技术来实现性能的最大化:

  1. 单进程、事件驱动模型显著降低了上下文切换的开销及内存占用
  2. 在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期及内存带宽
  3. 借助于Linux 2.6(>= 2.6.27.19)上的splice()系统调用,HAProxy可以实现零复制转发(Zero-copy forwarding),在Linux 3.5及以上的OS中还可以实现零复制启动(zero-starting)
  4. 内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长
  5. 树型存储:侧重于使用作者多年前开发的弹性二叉树, 实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列

了解了HAProxy后,接下来我们在192.168.243.167和192.168.243.168这两台机器上,分别搭建HAProxy节点。两台机器的搭建步骤都是一样的,这里以haproxy01为例。首先,安装一些工具:

[root@haproxy01 ~]# yum install -y gcc wget

然后到官网上复制源码包的下载链接,使用wget命令进行下载:

[root@haproxy01 ~]# cd /usr/local/src
[root@haproxy01 /usr/local/src]# wget http://www.haproxy.org/download/2.3/src/haproxy-2.3.1.tar.gz

解压下载好的源码包:

[root@haproxy01 /usr/local/src]# tar -zxvf haproxy-2.3.1.tar.gz
[root@haproxy01 /usr/local/src]# cd haproxy-2.3.1
[root@haproxy01 /usr/local/src/haproxy-2.3.1]# ls
BRANCHES  CHANGELOG  contrib  CONTRIBUTING  doc  examples  include  INSTALL  LICENSE  MAINTAINERS  Makefile  README  reg-tests  ROADMAP  scripts  src  SUBVERS  tests  VERDATE  VERSION
[root@haproxy01 /usr/local/src/haproxy-2.3.1]# 

执行如下命令进行编译安装:

[root@haproxy01 /usr/local/src/haproxy-2.3.1]# make TARGET=linux31 PREFIX=/usr/local/haproxy
[root@haproxy01 /usr/local/src/haproxy-2.3.1]# make install PREFIX=/usr/local/haproxy
[root@haproxy01 /usr/local/src/haproxy-2.3.1]# mkdir /etc/haproxy  # 创建配置文件存储目录

创建HAProxy的用户组和用户:

[root@haproxy01 ~]# groupadd -r -g 149 haproxy
[root@haproxy01 ~]# useradd -g haproxy -r -s /sbin/nologin -u 149 haproxy

创建HAProxy配置文件:

[root@haproxy01 ~]# vim /etc/haproxy/haproxy.cfg
#logging options
global
    log 127.0.0.1 local0 info
    maxconn 5120
    chroot /usr/local/haproxy
    uid 99
    gid 99
    daemon
    quiet
    nbproc 20
    pidfile /var/run/haproxy.pid

defaults
    log global
    #使用4层代理模式,”mode http”为7层代理模式
    mode tcp
    #if you set mode to tcp,then you nust change tcplog into httplog
    option tcplog
    option dontlognull
    retries 3
    option redispatch
    maxconn 2000
    timeout connect 5s
    #客户端空闲超时时间为 60秒 则HA 发起重连机制
    timeout client 60s
    #服务器端链接超时时间为 15秒 则HA 发起重连机制
    timeout server 15s  
    #front-end IP for consumers and producters

listen rabbitmq_cluster
    bind 0.0.0.0:5672
    #配置TCP模式
    mode tcp
    #balance url_param userid
    #balance url_param session_id check_post 64
    #balance hdr(User-Agent)
    #balance hdr(host)
    #balance hdr(Host) use_domain_only
    #balance rdp-cookie
    #balance leastconn
    #balance source //ip
    #简单的轮询
    balance roundrobin
    #rabbitmq集群节点配置 #inter 每隔五秒对mq集群做健康检查,2次正确证明服务器可用,2次失败证明服务器不可用,并且配置主备机制
    server rabbitmq01 192.168.243.164:5672 check inter 5000 rise 2 fall 2
    server rabbitmq02 192.168.243.165:5672 check inter 5000 rise 2 fall 2
    server rabbitmq03 192.168.243.166:5672 check inter 5000 rise 2 fall 2
#配置haproxy web监控,查看统计信息
listen stats
    bind 192.168.243.167:8100
    mode http
    option httplog
    stats enable
    #设置haproxy监控地址为http://localhost:8100/rabbitmq-stats
    stats uri /rabbitmq-stats
    stats refresh 5s

启动haproxy:

[root@haproxy01 ~]# /usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg

检查haproxy进程是否正常:

[root@haproxy01 ~]# netstat -lntp |grep 8100
tcp        0      0 192.168.243.167:8100    0.0.0.0:*               LISTEN      3414/haproxy        
[root@haproxy01 ~]# 

浏览器访问http://192.168.243.167:8100/rabbitmq-stats,可以在该页面查看一些监控统计信息:

image.png


RabbitMQ集群整合高可用组件KeepAlived

使用HAProxy实现了RabbitMQ集群的负载均衡后,应用端就可以通过HAProxy来访问RabbitMQ集群,但是HAProxy自身还是存在单点问题,HAProxy挂掉就无法访问其后端的RabbitMQ集群了。因此,我们需要结合KeepAlived组件实现两个HAProxy节点的主备切换,达到高可用的目的。

KeepAlived软件主要是通过VRRP协议实现高可用功能的。VRRP是Virtual Router RedundancyProtocol(虚拟路由器冗余协议)的缩写,VRRP出现的目的就是为了解决静态路由单点故障问题,VRRP是通过一种竞选机制来将路由的任务交给某台VRRP路由器的。它能够保证当个别节点宕机时,整个网络可以不间断地运行,所以Keepalived一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。

KeepAlived服务的三个重要功能:

  1. 管理LVS负载均衡软件
  2. 实现LVS集群节点的健康检查
  3. 作为系统网络服务的高可用性(failover)

Keepalived高可用服务对节点之间的故障切换转移,是通过VRRP来实现的。在Keepalived服务正常工作时,主Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活看,当主Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的IP资源及服务。而当主Master节点恢复时备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

接下来我们开始安装KeepAlived,同样的,我们需在192.168.243.167和192.168.243.168这两台机器上,分别安装KeepAlived。两台机器的安装步骤都是一样的,这里以haproxy01为例。

首先,安装一些编译时所依赖的工具包:

[root@haproxy01 ~]# yum install -y openssl openssl-devel psmisc

然后,到官网下载地址上复制下载链接:

然后使用wget命令进行下载:

[root@haproxy01 ~]# cd /usr/local/src
[root@haproxy01 /usr/local/src]# wget https://www.keepalived.org/software/keepalived-2.1.5.tar.gz

解压源码包并编译安装:

[root@haproxy01 /usr/local/src]# tar -zxvf keepalived-2.1.5.tar.gz 
[root@haproxy01 /usr/local/src]# cd keepalived-2.1.5
[root@haproxy01 /usr/local/src/keepalived-2.1.5]# ./configure --prefix=/usr/local/keepalived
[root@haproxy01 /usr/local/src/keepalived-2.1.5]# make && make install

创建配置文件存放目录,并创建keepalived的配置文件:

[root@haproxy01 ~]# mkdir /etc/keepalived
[root@haproxy01 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   router_id haproxy01  ##标识节点的字符串,通常为hostname
   script_user root
   enable_script_security
}

vrrp_script chk_haproxy {
    script "/etc/keepalived/haproxy_check.sh"  ##执行脚本位置
    interval 2  ##检测时间间隔
    weight -20  ##如果条件成立则权重减20
}

vrrp_instance VI_1 {
    state MASTER  ## 主节点为MASTER,备份节点为BACKUP
    interface ens32 ## 绑定虚拟IP的网络接口(网卡),与本机IP地址所在的网络接口相同(我这里是ens32)
    virtual_router_id 167  ## 虚拟路由ID号(主备节点一定要相同)
    mcast_src_ip 192.168.243.167 ## 本机ip地址
    priority 100  ##优先级配置(0-254的值)
    nopreempt
    advert_int 1  ## 组播信息发送间隔,俩个节点必须配置一致,默认1s
    authentication {  ## 认证匹配
        auth_type PASS
        auth_pass 123456
    }

    track_script {
        chk_haproxy
    }

    virtual_ipaddress {
        192.168.243.100  ## 虚拟ip,可以指定多个
    }
}

haproxy02节点(backup)的keepalived配置文件内容如下:

! Configuration File for keepalived

global_defs {
   router_id haproxy02  ##标识节点的字符串,通常为hostname
   script_user root
   enable_script_security
}

vrrp_script chk_haproxy {
    script "/etc/keepalived/haproxy_check.sh"  ##执行脚本位置
    interval 2  ##检测时间间隔
    weight -20  ##如果条件成立则权重减20
}

vrrp_instance VI_1 {
    state BACKUP  ## 主节点为MASTER,备份节点为BACKUP
    interface ens32 ## 绑定虚拟IP的网络接口(网卡),与本机IP地址所在的网络接口相同(我这里是ens32)
    virtual_router_id 167  ## 虚拟路由ID号(主备节点一定要相同)
    mcast_src_ip 192.168.243.168 ## 本机ip地址
    priority 90  ##优先级配置(0-254的值)
    nopreempt
    advert_int 1  ## 组播信息发送间隔,俩个节点必须配置一致,默认1s
    authentication {  ## 认证匹配
        auth_type PASS
        auth_pass 123456
    }

    track_script {
        chk_haproxy
    }

    virtual_ipaddress {
        192.168.243.100  ## 虚拟ip,可以指定多个
    }
}

编写haproxy的健康检查脚本(两个节点该文件内容一致即可):

[root@haproxy01 ~]# vim /etc/keepalived/haproxy_check.sh
#!/bin/bash
COUNT=`ps -C haproxy --no-header |wc -l`
if [ $COUNT -eq 0 ];then
    /usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg
    sleep 2
    if [ `ps -C haproxy --no-header |wc -l` -eq 0 ];then
        killall keepalived
    fi
fi

为检查脚本赋予可执行权限:

[root@haproxy01 ~]# chmod a+x /etc/keepalived/haproxy_check.sh

经过以上步骤在两个节点上均安装好keepalived后,就可以分别在两个节点上使用如下命令启动keepalived了:

$ systemctl start keepalived

检查keepalived的服务状态:

[root@haproxy01 ~]# systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since 六 2020-11-28 17:42:06 CST; 7s ago
  Process: 9722 ExecStart=/usr/local/keepalived/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/keepalived.service
           ├─9723 /usr/local/keepalived/sbin/keepalived -D
           └─9724 /usr/local/keepalived/sbin/keepalived -D

11月 28 17:42:06 haproxy01 Keepalived_vrrp[9724]: VRRP_Script(chk_haproxy) succeeded
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: (VI_1) Receive advertisement timeout
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: (VI_1) Entering MASTER STATE
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: (VI_1) setting VIPs.
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: (VI_1) Sending/queueing gratuitous ARPs on ens32 for 192.168.243.100
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: Sending gratuitous ARP on ens32 for 192.168.243.100
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: Sending gratuitous ARP on ens32 for 192.168.243.100
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: Sending gratuitous ARP on ens32 for 192.168.243.100
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: Sending gratuitous ARP on ens32 for 192.168.243.100
11月 28 17:42:10 haproxy01 Keepalived_vrrp[9724]: Sending gratuitous ARP on ens32 for 192.168.243.100
[root@haproxy01 ~]# 

高可用测试

安装好Keepalived之后,此时可以看到VIP在haproxy01这个节点上:

[root@haproxy01 ~]# ip a |grep 192.168.243.100
    inet 192.168.243.100/32 scope global ens32
[root@haproxy01 ~]# 

我们来模拟下节点宕机,看看VIP能否正常漂移到haproxy02节点上。将Keepalived服务给停掉:

[root@haproxy01 ~]# systemctl stop keepalived
[root@haproxy01 ~]# killall keepalived

此时haproxy01节点上已经没有绑定VIP了:

[root@haproxy01 ~]# ip a |grep 192.168.243.100
[root@haproxy01 ~]# 

正常情况下VIP会漂移到haproxy02节点上,使得该节点的haproxy可以继续对外提供服务,实现双机热备的高可用模式:

[root@haproxy02 ~]# ip a |grep 192.168.243.100
    inet 192.168.243.100/32 scope global ens32
[root@haproxy02 ~]# 

RabbitMQ集群恢复与故障转移的5种解决方案

本小节简单介绍下常见的RabbitMQ镜像队列集群故障恢复的解决方案和应用场景,假设我们现在有两个节点A和B组成的一个镜像队列集群,其中B是Master,A是Slave。

场景1:A先停,B后停
方案1:该场景下B是Master,只要先启动B,再启动A即可。或者先启动A,在30秒之内启动B即可恢复镜像队列

场景2:A、B同时停机
方案2:该场景可能是由于机房掉电等原因造成的,只需在30秒之内连续启动A和B即可恢复镜像

场景3:A先停,B后停,且A无法恢复
方案3:该场景是1场景的加强版,因为B是Master,所以等B起来以后,在B节点上调用控制台命令:rabbitmqctl forget_cluster_node A解除与A的Cluster关系,再将新的Slave节点加入B即可重新恢复镜像队列

场景4:A先停,B后停,且B无法恢复
方案4:该场景是场景3的加强版,比较难处理,原因是因为Master节点无法恢复。在3.1.x时代之前没有什么好的解决方案,因为B是主节点,所以直接启动A是不行的。当A无法启动的时候,也就没办法在A节点上调用之前的rabbitmqctl forget_cluster_node B命令了。但是现在已经有解决方案了,在3.4.2以后的版本中,forget_cluster_node支持--offline参数。这就意味着允许rabbitmqctl在理想节点上执行该命令,迫使RabbitMQ在未启动Slave节点中选择一个节点作为Master。当在A节点执行rabbitmqctl forget_cluster_node --offline B时,RabbitMQ会mock一个节点代表A,执行forget_cluster_node命令将B踢出Cluster,然后A就可以正常启动了,最后将新的Slave节点加入集群即可重新恢复镜像队列

场景5:A先停、B后停, 且A、B均无法恢复,但是能得到A或B的磁盘文件
方案5:这种场景更加难处理,只能通过恢复数据的方式去尝试恢复,将A或B的数据库文件(默认在$RABBIT_HOME/var/lib/目录中)拷贝到新节点对应的目录下,再将新节点的hostname改成A或B的hostname,如果是A节点(Slave)的磁盘文件,则按照场景4处理即可,如果是B节点(Master)的磁盘文件,则按照场景3处理,最后将新的Slave加入到新节点后完成恢复


RabbitMQ集群延迟队列插件应用

延迟插件的作用:

  • 延迟插件可以实现消息的延迟推送、定时任务(消息)的执行。包括一些消息重试策略的配合使用,以及用于业务削峰限流、降级的异步延迟消息机制,都是延迟队列的实际应用场景

我们来安装一下这个插件,该插件可以在Github仓库上下载到:

我们也可以到官网上获取官方提供的一些插件:

将下载好的插件上传到服务器上:

[root@rabbitmq01 ~]# ls
rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez
[root@rabbitmq01 ~]# 
  • Tips:注意插件版本尽量要与RabbitMQ的版本一致,避免版本不兼容导致的问题

将插件包拷贝到RabbitMQ的插件目录下:

[root@rabbitmq01 ~]# cp rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.9/plugins/

集群模式下还需要将该插件包分发给其他RabbitMQ节点,也是放到插件目录下:

[root@rabbitmq01 ~]# scp rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez rabbitmq02:/usr/lib/rabbitmq/lib/rabbitmq_server-3.8.9/plugins/
[root@rabbitmq01 ~]# scp rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez rabbitmq03:/usr/lib/rabbitmq/lib/rabbitmq_server-3.8.9/plugins/

在集群的各个节点中执行如下命令启用该插件:

$ rabbitmq-plugins enable rabbitmq_delayed_message_exchange

插件启用成功后,我们到管控台上新建一个延迟消息类型的Exchange:


image.png

然后创建一个队列:


image.png

将该队列绑定到Exchange上:


image.png

尝试发送一条延迟消息:


image.png

此时到队列界面上,可以看到队列中并没有任何消息:


image.png

等待15秒后,队列中就有一条消息了:


image.png

查看消息的内容如下:


image.png

能达到这个延迟投递的效果,代表我们的延迟消息插件安装成功,并且能够正常投递延迟消息了。该插件在实际开发中,应用得非常广泛,有兴趣的小伙伴可以继续深入了解下。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容