• RabbitMQ集群搭建


    一、前提

    • erlang安装版本一致
    • RabbitMQ安装版本一致
    • 下面的例子以192.168.73.134与192.168.73.135为服务器搭建Rabbitmq集群.

    二、RabbitMQ集群

    RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言,但其本身并不支持负载均衡。Rabbit模式大概分为以下三种:单一模式、普通模式、镜像模式。

    • 单一模式:最简单的情况,非集群模式。

    • 普通模式:默认的集群模式。

        对于Queue来说,消息实体只存在于其中一个节点,A、B两个节点仅有相同的元数据,即队列结构。
        
        当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行消息传输,把A中的消息实体取出并经过B发送给consumer。
        所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连A或B,出口总在A,会产生瓶颈。
        
        该模式存在一个问题就是当A节点故障后,B节点无法取到A节点中还未消费的消息实体。
        
        如果做了消息持久化,那么得等A节点恢复,然后才可被消费;如果没有持久化的话,然后就没有然后了……
      
    • 镜像模式:把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的HA方案。

        该模式解决了上述问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。
        
        该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。
        
        所以在对可靠性要求较高的场合中适用(后面会详细介绍这种模式,目前我们搭建的环境属于该模式)。
      

    2.1 集群中的基本概念

    RabbitMQ的集群节点包括内存节点、磁盘节点。

    顾名思义内存节点就是将所有数据放在内存,磁盘节点将数据放在磁盘。不过,如前文所述,如果在投递消息时,打开了消息的持久化,那即使是内存节点,数据还是安全的放在磁盘。

    一个RabbitMQ集群中可以共享user、vhost、queue、exchange等,所有的数据和状态都是必须在所有节点上复制的,一个例外是那些当前只属于创建它的节点的消息队列,尽管它们可见且可被所有节点读取。RabbitMQ节点可以动态地加入到集群中,一个节点它可以加入到集群中,也可以从集群环集群进行一个基本的负载均衡。

    集群中有两种节点:

    • 内存节点:只保存状态到内存(一个例外的情况是:持久的queue的持久内容将被保存到disk)

    • 磁盘节点:保存状态到内存和磁盘。

    内存节点虽然不写入磁盘,但是它执行比磁盘节点要好。集群中,只需要一个磁盘节点来保存状态 就足够了
    如果集群中只有内存节点,那么不能停止它们,否则所有的状态,消息等都会丢失。

    思路:
    那么具体如何实现RabbitMQ高可用,我们先搭建一个普通集群模式,在这个模式基础上再配置镜像模式实现高可用,Rabbit集群前增加一个反向代理,生产者、消费者通过反向代理访问RabbitMQ集群。

    架构图如下:

     

    2.2 集群模式配置

    step1: 局域网配置
    在安装好的三台节点服务器中,分别修改/etc/hosts文件
    1. vim /etc/hosts
    
    192.168.73.134 node1
    192.168.73.135 node2
    
    step2: 设置不同节点间同一认证的Erlang Cookie
    Erlang的集群中各节点是通过一个magic cookie来实现的,这个cookie存放在 /var/lib/rabbitmq/.erlang.cookie 中,文件是400的权限。
    所以必须保证各节点cookie保持一致,否则节点之间就无法通信。
    采用从主节点copy的方式保持Cookie的一致性:
    
    1. chmod 777  /var/lib/rabbitmq/.erlang.cookie
    2. scp -p 22 /var/lib/rabbitmq/.erlang.cookie root@192.168.73.135:/var/lib/rabbitmq/
    
    复制好后查看文件所属用户和组以及权限是否满足要求,不满足则修改。之后还原.erlang.cookie的权限,否则可能会遇到错误:
    3. chown rabbitmq:rabbitmq .erlang.cookie
    4. chmod 400 /var/lib/rabbitmq/.erlang.cookie
    
    step3: 使用 -detached运行各节点
    设置好cookie后将各个节点的RabbitMQ重启:
    1. cd /sbin
    2. rabbitmqctl stop
    3. rabbitmq-server start
    
    这里正常重启可能会提示该节点示例已经再运行中。如果出现使用以下命令启动:
    1. ps -aux | grep erl
    2. kill -9 {pid}
    3. RABBITMQ_NODE_PORT=5678 RABBITMQ_NODENAME=rabbit@node1 ./rabbitmq-server -detached
        RABBITMQ_NODE_PORT=5678 RABBITMQ_NODENAME=rabbit@node2 ./rabbitmq-server -detached
    
    ps:上面5678是因为在安装时将rabbitmq的端口修改为5678了,而nodename与hosts里面设置的保持一致。
        依次启动所有节点。
    
    step4: 查看各节点的状态
    1. 查看启动端口:  netstat -lntp 
    
        Active Internet connections (only servers)
        Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
        tcp        0      0 0.0.0.0:4369            0.0.0.0:*               LISTEN      27321/epmd          
        tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      760/sshd            
        tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1066/master         
        tcp        0      0 0.0.0.0:15678           0.0.0.0:*               LISTEN      27862/beam.smp      
        tcp        0      0 0.0.0.0:25672           0.0.0.0:*               LISTEN      27862/beam.smp      
        tcp6       0      0 :::5678                 :::*                    LISTEN      27862/beam.smp      
        tcp6       0      0 :::8080                 :::*                    LISTEN      964/java            
        tcp6       0      0 :::4369                 :::*                    LISTEN      27321/epmd          
        tcp6       0      0 :::22                   :::*                    LISTEN      760/sshd            
        tcp6       0      0 ::1:25                  :::*                    LISTEN      1066/master         
        tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      964/java            
        tcp6       0      0 :::8009                 :::*                    LISTEN      964/java
    
    2. 查看rabbitmq启动状态:  
        rabbitmqctl -n rabbit1
    step5: 创建并部署集群
    将rabbit
    step5: 查看集群状态
    1.查看节点1的集群状态:   rabbitmqctl -n rabbit
     
    至此,rabbitmq集群搭建完毕。
    

    三、RabbitMQ镜像模式

    上面配置RabbitMQ默认集群模式,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制,虽然该模式解决一部分节点压力,但队列节点宕机直接导致该队列无法使用,只能等待重启,所以要想在队列节点宕机或故障也能正常使用,就要复制队列内容到集群里的每个节点,需要创建镜像队列。

    step1:增加负载均衡器

    关于负载均衡器,商业的比如F5的BIG-IP,Radware的AppDirector,是硬件架构的产品,可以实现很高的处理能力。但这些产品昂贵的价格会让人止步,所以我们还有软件负载均衡方案。互联网公司常用的软件LB一般有LVS、HAProxy、Nginx等。LVS是一个内核层的产品,主要在第四层负责数据包转发,使用较复杂。HAProxy和Nginx是应用层的产品,但Nginx主要用于处理HTTP,所以这里选择HAProxy作为RabbitMQ前端的LB。

    1. 安装HAProxy(在192.168.73.136上安装HAProxy)
        yum -y install haproxy
    
    2. 修改haproxy.config配置
        vim /etc/haproxy/haproxy.config
        在其中增加以下配置:
        listen rabbitmq_cluster 0.0.0.0:5678
            mode tcp
            balance roundrobin
            server rabbitmaster 192.168.73.134:5678 check inter 2000 rise 2 fall 3
            server rabbitslave 192.168.73.135:5678 check inter 2000 rise 2 fall 3
    

    修改完HaProxy配置之后重新启动可能会提示绑定端口失败,此时执行以下命令即可:

        setsebool -P haproxy_connect_any=1
    

    负载均衡器会监听192.168.73.136的5678端口,轮询我们的两个节点192.168.73.134、192.168.73.135的5678端口,这样磁盘节点除了故障也不会影响,除非同时出故障。

    step2:配置Rabbitmq策略

    在任意一个节点上执行:

        rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
        上面的命令会将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态保持一致
    
    step3:使用负载服务器发送消息

    客户端使用负载服务器172.16.3.110 (panyuntao3)发送消息,队列会被复制到所有节点。到这里我们完成了RabbitMQ集群的高可用配置。

     

    作者:明天你好向前奔跑
    链接:https://www.jianshu.com/p/01527d177e12

  • 相关阅读:
    用grunt搭建自动化的web前端开发环境-完整教程
    SQL Server:触发器详解
    利用junit对springMVC的Controller进行测试
    jquery-barcode:js实现的条码打印
    16个良好的 Bootstrap Angularjs 管理后台主题
    Spring Security 4 Hello World Annotation+XML
    intellij 13新建javaweb项目并用tomcat 7启动
    JavaScript类和继承:constructor属性
    javascript 的面相对象
    javascript call apply bind caller callee 的用法
  • 原文地址:https://www.cnblogs.com/-wenli/p/13396851.html
Copyright © 2020-2023  润新知