背景

Javashop电商系统的消息总线使用的事rabbitmq,在订单创建、静态页生成、索引生成等等业务中大量采用异步消息系统,这个对于mq高可用的要求有两个重要的考量:

1、集群化

2、可扩容

3、冗灾

冗灾就要实现rabbitmq的持久化,要考虑到rabbitmq宕机的情况,当rabbitmq因不可抗因素挂掉了,这时有一些消息还没来得及被消费,当我们再恢复了rabbitmq的运行后,这些消息应该同时被恢复,可以再次被消费。

本文着重讨论rabbitmq的k8s的持久化部署方案,当然提供在方案也支持了集群及扩容。

思路

1、数据的存储

在k8s中的持久化部署不可避免的要用到持久卷,我们采用nfs方式的持久卷来存储es数据。

持久卷的详细介绍请见这里:

https://kubernetes.io/docs/concepts/storage/persistent-volumes/

2、多节点的权限问题

rabbit的数据目录默认只允许一个节点访问,但在k8s上采用了持久卷,所有节点的数据都存储在这个卷上,这会导致rabbitmq的数据目录访问权限问题:

     {{failed_to_cluster_with,
[rabbit@b8c4d82b52bc],
"Mnesia could not connect to any nodes."},
{rabbit,start,[normal,[]]}}

我们通过指定节点名称的方式来解决,稍后可以在配置文件中看到具体的配置项。

部署过程

一、pv(持久卷的建立)

先要建立nfs服务器

对于持久卷的结构规划如下:

 /nfs/data/mqdata

根据如上规划建立nfs服务:

 #master节点安装nfs
yum -y install nfs-utils
#创建nfs目录
mkdir -p /nfs/data/{mqdata,esmaster,esdata}
#修改权限
chmod -R /nfs/data/ #编辑export文件
vim /etc/exports 粘贴如下内容:
/nfs/data/mqdata *(rw,no_root_squash,sync) #配置生效
exportfs -r
#查看生效
exportfs #启动rpcbind、nfs服务
systemctl restart rpcbind && systemctl enable rpcbind
systemctl restart nfs && systemctl enable nfs #查看 RPC 服务的注册状况
rpcinfo -p localhost #showmount测试,这里的ip输入master节点的局域网ip
showmount -e <your ip>

如果成功可以看到可被挂载的目录:

 # showmount -e 172.17.14.73
Export list for 172.17.14.73:
/nfs/data/esmaster *
/nfs/data/mqdata *

接下来,要在每一个节点上安装nfs服务以便使k8s可以挂载nfs目录

 #所有node节点安装客户端
yum -y install nfs-utils
systemctl start nfs && systemctl enable nfs

这样就为k8s的持久卷做好了准备。

建立持久卷

有了nfs的准备,我就可以建立持久卷了:

我们分享了javashop内部使用的yaml仓库供大家参考:

https://gitee.com/enation/rabbitmq-on-kubernetes

在您的k8s maseter节点服务器上 clone我们准备好的yaml文件

https://gitee.com/javashop/rabbitmq-on-kubernetes

修改根目录中的pv.yaml

修改其中的server配置为nfs服务器的IP:

  nfs:
server: 192.168.1.100 #这里请写nfs服务器的ip

通过下面的命令建立持久卷:

 kubectl create -f pv.yaml

通过以下命令查看持久卷是否建立成功:

 kubectl get pv

部署rabbitmq

在k8s  master节点上执行下面的命令创建namespace:

 kubectl create namespace ns-rabbitmq

执行下面的命令创建rabbitmq集群(执行整个目录的所有配置文件)

 kubectl create -f rabbitmq/

通过以上部署我们建立了一个ns-rabbitmq的namespace,并在其中创建了相应的pvc、角色账号,有状态副本集以及服务。

镜像

使用的是javashop自己基于rabbitmq:3.8做的,加入了延迟消息插件,其他没有变化。

服务

我们默认开启了对外nodeport端口,对应关系:

31672->15672

30672->5672

k8s内部可以通过下面的服务名称访问:

rabbitmq.ns-rabbitmq:15672

rabbitmq.ns-rabbitmq:5672

等待容器都启动成功后验证。

验证

使用附带程序校验

  1. 发送消息(注释掉接收消息)

  2. 观察mq的队列中有消息堆积

  3. 删除mq的副本集

  4. 恢复mq副本集

  5. 接收消息

关键技术点

1、集群发现:

使用rabbitmq提供的k8s对等发现插件:rabbitmq_peer_discovery_k8s

2、映射持久卷

映射到:/var/lib/rabbitmq/mnesia

3、自定义数据目录

           - name: RABBITMQ_MNESIA_BASE
value: /var/lib/rabbitmq/mnesia/$(MY_POD_NAME)

其中MY_POD_NAME是读取的容器名称,通过有状态副本集保证唯一性的绑定:

           - name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace

附带验证程序

 private static CachingConnectionFactory connectionFactory;
private static void initConnectionFactory() {
connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
}
public static void main(String[] args) {
initConnectionFactory();
//发送消息
send();
//接收消息
receive();
}
private static void receive() {
AmqpTemplate template = new RabbitTemplate(connectionFactory);
String foo = (String) template.receiveAndConvert("myqueue");
System.out.println("get message : "+ foo);
}
private static void send() {
AmqpAdmin admin = new RabbitAdmin(connectionFactory);
admin.declareQueue(new Queue("myqueue",true));
AmqpTemplate template = new RabbitTemplate(connectionFactory);
template.convertAndSend("myqueue", "foo");
}

欢迎关注Javashop技术分享公众号,观看更多的视频讲解:

rabbitmq在kubernetes中持久化集群部署的更多相关文章

  1. (十)RabbitMQ消息队列-高可用集群部署实战

    原文:(十)RabbitMQ消息队列-高可用集群部署实战 前几章讲到RabbitMQ单主机模式的搭建和使用,我们在实际生产环境中出于对性能还有可用性的考虑会采用集群的模式来部署RabbitMQ. Ra ...

  2. Linux中Consul集群部署

    分配三台虚拟机: 192.168.5.125 192.168.5.128 192.168.5.129 在每台虚拟机上创建  /usr/consul 文件件  命令: mkdir /usr/consul ...

  3. Linux中Elasticsearch集群部署

    1.下载安装包elasticsearch-6.3.1  安装包自己下载,网上很多 2.安装位置在cd /usr/local/elasticsearch/目录下 3.因为ES使用root权限运行会报错, ...

  4. RabbitMQ集群部署、高可用和持久化

    RabbitMQ 安装和使用 1.安装依赖环境 在 http://www.rabbitmq.com/which-erlang.html 页面查看安装rabbitmq需要安装erlang对应的版本 在 ...

  5. RabbitMQ消息队列(十)-高可用集群部署实战

    前几章讲到RabbitMQ单主机模式的搭建和使用,我们在实际生产环境中出于对性能还有可用性的考虑会采用集群的模式来部署RabbitMQ. RabbitMQ集群基本概念 Rabbit模式大概分为以下三种 ...

  6. Centos6.9下RabbitMQ集群部署记录

    之前简单介绍了CentOS下单机部署RabbltMQ环境的操作记录,下面详细说下RabbitMQ集群知识,RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言, ...

  7. RabbitMQ的高可用集群部署

    RabbitMQ的高可用集群部署 标签(空格分隔): 消息队列 部署 1. RabbitMQ部署的三种模式 1.1 单一模式 单机情况下不做集群, 仅仅运行一个RabbitMQ. # docker-c ...

  8. Quartz.net持久化与集群部署开发详解

    序言 我前边有几篇文章有介绍过quartz的基本使用语法与类库.但是他的执行计划都是被写在本地的xml文件中.无法做集群部署,我让它看起来脆弱不堪,那是我的罪过. 但是quart.net是经过许多大项 ...

  9. rabbitMQ集群部署以及集群之间同步

    MQ集群部署 期待的部署架构 其中,一个机房有两台机器部署MQ,并组成集群,有一个机房的MQ集群作为中心集群,其他机房的MQ集群将消息同步到中心MQ集群中. 安装erlang,略.. 安装rabbit ...

随机推荐

  1. 悄摸直播 —— JavaCV实现本机摄像头画面远程直播

    目录 前言 需要的jar包和依赖 需要实现的模块(附带源码教程) 项目效果展示 前言 最近想用Java实现一个类似于远程直播的功能 像这样:(功能示意图) 需要的jar包和依赖 Maven依赖: &l ...

  2. docker 批量删除 镜像 容器

    我们在docker构建和测试时,经常会产生很多无用的镜像或者容器,我们可用如下两条命令一个一个删除. docker container rm 容器id #删除容器 可简写: docker rm 容器i ...

  3. cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

    186. [USACO Oct08] 牧场旅行 ★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比时间限制:1 s   内存限制:128 MB n个被自然地编号为 ...

  4. hdu 5139 数据的离线处理

    所谓的数据离线处理,就是将所有的输入数据全部读入后,在进行统一的操作,这样当然有好处,比如让你算好多数的阶层,但是输入的每个数是没有顺序的,其实跟可以线性的解决,但是由于没有顺序的输入,这样处理的话复 ...

  5. Eclipse常用快捷键【转】

    Eclipse的编辑功能非常强大,掌握了Eclipse快捷键功能,能够大大提高开发效率.Eclipse中有如下一些和编辑相关的快捷键.1. [ALT+/]此快捷键为用户编辑的好帮手,能为用户提供内容的 ...

  6. cf 697C Lorenzo Von Matterhorn 思维

    题目链接:https://codeforces.com/problemset/problem/697/C 两种操作: 1是对树上u,v之间的所有边的权值加上w 2是查询树上u,v之间的边权和 树是满二 ...

  7. macOS 10.11.* 安装scrapy

    1.安装brew,然后修改brew源为某高校 2.更新python brew install python 3.安装pip 4.安装scrapy,这里肯定会有一个坑,之前在网上看到10.11开启了什么 ...

  8. numpy 数组的拼接

    一.数组的拼接 1.水平拼接 a.格式 np.hstack((数组1, 数组2)) # 注意: 值是元祖 # 0轴长要相同 b.例子 import numpy as np arr1 = np.aran ...

  9. unbuntu18.04安装启用splash

    官网:https://splash.readthedocs.io/en/stable/ 1.安装Docker https://www.cnblogs.com/wt7018/p/11880666.htm ...

  10. lisp学习总结(一)

    lisp太简单 lisp核心太简单了只有几个简单的逻辑定理,简单到你会认为他啥事都做不了. lisp语法太简单了,只有符号,参数,以及括号,组成一种万能的表达式. 由于上述lisp的简单,所以对于初学 ...