全栈工程师开发手册 (作者:栾鹏)
架构系列文章


rabbit原理和架构可以参考https://blog.csdn.net/luanpeng825485697/article/details/82082751

docker部署rabbitmq

在docker环境部署RabbitMQ

RabbitMQ是用 Erlang 编写的,直接部署的话需要先部署 Erlang 环境,比较麻烦。在 docker 环境下部署就比较简单了,直接使用rabbitmq官方提供的镜像即可。

登录 docker 节点,运行

docker pull rabbitmq:management

这里使用的是带 web 管理插件的镜像。

或者我们可以自己封装镜像,以方便扩展

Dockerfile文件内容如下


FROM rabbitmq:management
# 启用记录插件
RUN rabbitmq-plugins enable rabbitmq_tracing

运行下面的命令进行封装。本次封装的内容为日志跟踪,在页面的admin中有tracking,创建跟踪以后会自动订阅消息,保存在日志文件中。这样可以方便查看历史消息。

# docker build -t luanpeng/lp:rabbitmq-management .

启动容器:

docker run -d --name rabbitmq --publish 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management

容器启动之后就可以访问web 管理端了 http://127.0.0.1:15672,默认创建了一个 guest 用户,密码也是 guest。

好了,RabbitMQ已经启动成功了,然后我们来实践一下。

先添加两个Exchange(camera_exchange、screen_exchange)和两个queue(carema_queue、screen_queue)都选择topic模式


为camera_exchange绑定camera_queue,并绑定两个路由(过滤条件)ca1.#和ca2.#

为screen_exchange绑定screen_queue,并绑定两个路由(过滤条件)sc1.#和sc2.#

exchange和queue可以多对多绑定。

这样就可以在exchange中发送消息了。消息包含key(Routing key)和message(Payload)。exchange接收消息后通过key值选择将消息发送到哪个queue。

在queue中接收消息

k8s部署rabbit集群

消息中间件rabbitmq,一般以集群方式部署,主要提供消息的接受和发送,实现各微服务之间的消息异步。本篇将以rabbitmq+HA方式进行部署。

一、原理介绍

rabbitmq是依据erlang的分布式特性(RabbitMQ底层是通过Erlang架构来实现的,所以rabbitmqctl会启动Erlang节点,并基于Erlang节点来使用Erlang系统连接RabbitMQ节点,在连接过程中需要正确的Erlang Cookie和节点名称,Erlang节点通过交换Erlang Cookie以获得认证)来实现的,所以部署rabbitmq分布式集群时要先安装erlang,并把其中一个服务的cookie复制到另外的节点。

rabbitmq集群中,各个rabbitmq为对等节点,即每个节点均提供给客户端连接,进行消息的接收和发送。节点分为内存节点和磁盘节点,一般的,均应建立为磁盘节点,为了防止机器重启后的消息消失;

RabbitMQ的Cluster集群模式一般分为两种,普通模式和镜像模式。消息队列通过rabbitmq HA镜像队列进行消息队列实体复制。

普通模式下,以两个节点(rabbit01、rabbit02)为例来进行说明。对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01、rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer。所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。

镜像模式下,将需要消费的队列变为镜像队列,存在于多个节点,这样就可以实现RabbitMQ的HA高可用性。作用就是消息实体会主动在镜像节点之间实现同步,而不是像普通模式那样,在consumer消费数据时临时读取。缺点就是,集群内部的同步通讯会占用大量的网络带宽。

二、集群部署方案

本方案中是在多台机器之间部署rabbitmq的cluster,要求如下:这几个节点需要在同一个局域网内;这几个节点需要有相同的erlang cookie,否则不能正常通信,为了实现cookie内容一致,采用scp的方式进行。

这里仍然使用上面的镜像rabbitmq:management,因为上面的镜像中已经安装了erlang和rabbit

rabbit在目录/usr/lib/rabbitmq

erlang在目录/usr/lib/erlang

设置erlang

找到erlang cookie文件的位置,官方在介绍集群的文档中提到过.erlang.cookie一般会存在这两个地址:第一个是$home/.erlang.cookie;第二个地方就是/var/lib/rabbitmq/.erlang.cookie。如果我们使用解压缩方式安装部署的rabbitmq,那么这个文件会在${home}目录下,也就是$home/.erlang.cookie。如果我们使用rpm等安装包方式进行安装的,那么这个文件会在/var/lib/rabbitmq目录下。

在rabbitmq:management镜像查看文件

cat ~/.erlang.cookie

这里将 node1 的该文件复制到 node2、node3,注意这个文件的权限是 400(默认即是400),因此采用scp的方式只拷贝内容即可;

可以通过cat $~/.erlang.cookie来查看三台机器的cookie是否一致,设置erlang的目的是要保证集群内的cookie内容一致。

k8s部署

首先说明一下,rabbitmq是使用autocluster插件去调用kubernetes apiserver获取rabbitmq服务的endpoints获取node节点信息,并加入集群的。下面开始操作:

# 集群中的每个rabbitmq都要是相同的cookie
echo $(openssl rand -base64 32) > erlang.cookie
kubectl create secret generic erlang.cookie --from-file=erlang.cookie   -n cloudai-2 kubectl create -f rabbitmq-serviceAccount.yaml
kubectl create -f rabbitmq-service.yaml
kubectl create -f rabbitmq-deployment.yaml

其中rabbitmq-serviceAccount.yaml为

---
apiVersion: v1
kind: ServiceAccount    # 也就是pod在k8s中的角色。kubectl是admin角色。Service Account 是 Kubernetes 用于集群内运行的程序,进行服务发现时调用 API 的帐号,帐号的 token 会直接挂载到 Pod 中,可以供程序直接使用。
metadata:name: rabbitmqnamespace: cloudai-2
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: rabbitmqnamespace: cloudai-2
rules:- apiGroups:- ""resources:- endpointsverbs:- get
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:name: rabbitmqnamespace: cloudai-2
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: rabbitmq
subjects:
- kind: ServiceAccountname: rabbitmqnamespace: cloudai-2

rabbitmq-service.yaml文件为

apiVersion: v1
kind: Service
metadata:labels:app: rabbitmqname: rabbitmqnamespace: cloudai-2
spec:ports:- port: 5672name: port-5672protocol: TCPtargetPort: 5672    - port: 4369name: port-4369protocol: TCPtargetPort: 4369    - port: 5671name: port-5671protocol: TCPtargetPort: 5671    - port: 15672name: port-15672protocol: TCPtargetPort: 15672    - port: 25672name: port-25672protocol: TCPtargetPort: 25672    selector:app: rabbitmq    # 选择podexternalIPs:- 192.168.2.177    # 这里要更改一下,只在指定的外部ip上监听,而非像nodeport所有节点监听.  只用externalIPs:port  访问

rabbitmq-deployment.yaml文件为

apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: rabbitmqnamespace: cloudai-2labels:app: rabbitmq  version: v1.0.0
spec:selector:    matchLabels:app: rabbitmqversion: v1.0.0replicas: 1template:metadata:labels:app: rabbitmqversion: v1.0.0spec:serviceAccountName: rabbitmqvolumes: - name: tz-confighostPath:path: /usr/share/zoneinfo/Asia/Shanghai- name: config-path  persistentVolumeClaim:claimName: pvc-rabbirmqcontainers:- name: rabbitmqimage: rabbitmq:managementimagePullPolicy: IfNotPresentports:- containerPort: 5672name: port-5672- containerPort: 4369name: port-4369- containerPort: 5671name: port-5671- containerPort: 15672name: port-15672- containerPort: 25672name: port-25672env:- name: AUTOCLUSTER_TYPEvalue: "k8s"- name: AUTOCLUSTER_DELAYvalue: "10"- name: AUTOCLUSTER_CLEANUPvalue: "true"- name: RABBITMQ_DEFAULT_USERvalue: intellif                        # 连接rabbit的账号- name: RABBITMQ_DEFAULT_PASSvalue: introcks                       #连接rabbit的密码- name: HOSTNAMEvalueFrom:fieldRef:fieldPath: status.podIP- name: MY_POD_IPvalueFrom:fieldRef:fieldPath: status.podIP- name: CLEANUP_INTERVALvalue: "60"- name: CLEANUP_WARN_ONLYvalue: "false"- name: K8S_SERVICE_NAMEvalue: "rabbitmq"- name: K8S_ADDRESS_TYPEvalue: "hostname"- name: K8S_HOSTNAME_SUFFIXvalue: ".$(K8S_SERVICE_NAME)"- name: RABBITMQ_USE_LONGNAMEvalue: "true"- name: K8S_HOSTvalue: "192.168.0.52"               #   修改ip,因为- name: K8S_PORT                       #   修改端口号value: "6443"- name: RABBITMQ_ERLANG_COOKIEvalueFrom:secretKeyRef:name: erlang.cookiekey: erlang.cookieresources:       limits:cpu: 500mmemory: 1024Mirequests:cpu: 10mmemory: 100MivolumeMounts:- name: tz-configmountPath: /etc/localtime- name: config-pathmountPath: /var/lib/rabbitmq

部署高可用的rabbitmq

我们上面部署pod仅部署了一遍, pod重启, rabbitmq的元消息会丢失, 如果部署高可用的rabbit.

参考:https://www.kubernetes.org.cn/2629.html

REST API

有时需要初始化一些列队列和交换器,每次部署一套新环境后,都需要一步一步创建会有点麻烦,通过REST API可方便的实现自动化脚本。
当启用web管理插件后,不仅获得了WEB UI,也拥一个REST化的WEB管理API,任何语言或脚本只要有HTTP库,都能调用。
接口会返回json串,比如获取所有队列:

curl -i -u admin:admin http://xx.xx.xx.xx:15672/api/queues

会返回一个json数组,每个元素是一个队列,包含队列的各种属性:

[{"arguments":{},"auto_delete":false,"backing_queue_status":{"avg_ack_egress_rate":0.0,"avg_ack_ingress_rate":0.0,"avg_egress_rate":0.0,"avg_ingress_rate":0.0,"delta":["delta","undefined",0,0,"undefined"],"len":0,"mode":"default","next_seq_id":0,"q1":0,"q2":0,"q3":0,"q4":0,"target_ram_count":0},"consumer_utilisation":null,"consumers":1,"durable":false,"effective_policy_definition":[],"exclusive":true,"exclusive_consumer_tag":null,"garbage_collection":{"fullsweep_after":65535,"max_heap_size":0,"min_bin_vheap_size":46422,"min_heap_size":233,"minor_gcs":291},"head_message_timestamp":null,"idle_since":"2019-02-28 ..
...

要想知道rest能获取什么样的数据,和,他们具有什么样的接口,可以参考

http://xx.xx.xx.xx:15672/api/index.html

注意:在该界面看到的接口,斜体表示变量,需要自己根据需要更改。

rabbitmqadmin脚本

另外,还提供了rabbitmqadmin脚本的方式查看元数据信息和一些统计数据,它会包装REST API,使用干净的接口与其交互,而且输出内容也是格式化过的,方便我们查看。

比如查看所有队列,可以这样写:

./rabbitmqadmin list queues

会返回如下结果:

监控

监控RabbitMQ并不只是确保端口5672是开启的并能接收TCP连接而已,还要能够模拟AMQP客户端来确保连接之后获取信道,如果能使用REST API找出是否所有构成RabbitMQ部件都正常运行,并且之间能正常通信,就更好了。

监控RabbitMQ的各个方面,比如:监控Rabbit内部状态、确认RabbitMQ可用并且能够响应、观察队列状态检测消费者异常、检测消息通信结构中不合需求的配置更改等。

采用RabbitMQ提供的restful http api来做监控其实很简单,只需调用(比如HttpClient工具):http://server-ip:15672/api/nodes即可。下面展示下博主这里的某些监控指标:broker节点的内存占用,磁盘剩余空间,Socket句柄,Broker子进程数,文件句柄数。

docker 部署rabbitmq,k8s部署rabbitmq集群,跟踪和监控rabbitmq相关推荐

  1. mqtt安装使用教程。(基于rabbitmq插件,docker部署,k8s部署,python教程)

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 Docker安装RabbitMQ配置MQTT 使用RabbitMQ作为MQTT服务端,Eclipse Paho作为客户端.宿主机系统为ubuntu16 ...

  2. RabbitMQ#RabbitMQ+Haproxy消息队列集群和代理部署

    文章目录 一.消息队列/中间件 1.RabbitMQ本质上起到的作用就是削峰填谷 2.MQ简介(RabbitMQ比Kafka) 3.MQ消息队列的分类 二.RabbitMQ介绍(端口15672) 1. ...

  3. docker 如何加入kubernetes_使用 Kind 在 5 分钟内快速部署一个 Kubernetes 高可用集群...

    什么是 Kind Kind(Kubernetes in Docker) 是一个Kubernetes孵化项目,Kind是一套开箱即用的Kubernetes环境搭建方案.顾名思义,就是将Kubernete ...

  4. ansible-playbook部署K8S高可用集群

    通过ansible-playbook,以Kubeadm方式部署K8S高可用集群(多主多从). kubernetes安装目录: /etc/kubernetes/KubeConfig: ~/.kube/c ...

  5. k8s高可用集群搭建部署

    简介 k8s普通搭建出来只是单master节点,如果该节点挂掉,则整个集群都无法调度,K8s高可用集群是用多个master节点加负载均衡节点组成,外层再接高可用分布式存储集群例如ceph集群,实现计算 ...

  6. 部署一套完整的K8s高可用集群(二进制-V1.20)

    <部署一套完整的企业级K8s集群> v1.20,二进制方式 作者信息 李振良(阿良),微信:xyz12366699 DevOps实战学院 http://www.aliangedu.cn 说 ...

  7. 【Docker之Swarm详细讲解Swarm集群搭建管理节点工作节点Raft一致性协议overlay网络Docker结合Swarm部署WordPress个人博客实战】

    一.知识回顾 之前的内容都帮你整理好了,在这里哟! [0.Docker相关目录文章整理,可自行查看,包含多节内容] [1.Docker详细安装部署&阿里镜像地址配置] [2.Docker架构& ...

  8. Redis 集群搭建(三):Docker 部署 Redis + Sentinel 高可用集群

    Redis 集群搭建(三):Docker 部署 Redis + Sentinel 高可用集群 前言 建议 官方译文 什么是 Sentinel? Sentinel 优点 Redis 配置文件 maste ...

  9. k8s高可用集群_搭建高可用集群(初始化和部署keepalived)---K8S_Google工作笔记0055

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 然后我们来部署keepalived,搭建高可用集群. 然后我们这里需要master,155, ma ...

最新文章

  1. dabs是什么意思_单词flounder是什么中文意思
  2. 在Oracle中如何让SELECT查询绕过UNDO
  3. 200917阶段一C++双向链表模板
  4. 怎样写APP计划书-20150313早读课
  5. 声速的测量的实验原理和应用_CEMS烟气在线分析仪测量原理计经典应用
  6. php mysql bool_关于mysql api中my_bool的取值范围的问题
  7. 新书问答:Agile Management
  8. ng service(服务)
  9. Centos7 Zabbix3.2安装(yum)
  10. Python语言介绍
  11. Python 的输出矩阵的一些常用设置
  12. HTTPS(三)之JAVA 不校验HTTPS服务器证书
  13. 使用Camera X遇到的坑_OnPause时没有释放相机导致回来时黑屏
  14. 影响stable diffusion的embedding训练效率的部分问题和拟解决办法
  15. 桌面计算机最小化,最小化我的电脑窗口打开总是最小化,如何把它 – 手机爱问...
  16. 2019-2020-2 20175227张雪莹《网络对抗技术》 Exp2 后门原理与实践
  17. 不要和负能量的人交朋友
  18. 花式索引与np.ix_函数
  19. 2018年互联网发展趋势预测
  20. 【C生万物】 结构体篇

热门文章

  1. 语音识别中的MFCC的提取原理和MATLAB实现
  2. 有关语音识别技术的一些信息点
  3. oracle锁表自动解锁,oracle 锁表,解锁,批量解锁
  4. php用手机摇一摇,H5做出手机摇一摇功能的实现步骤
  5. FFmpeg源代码简单分析:avformat_alloc_output_context2()
  6. redhat linux 7 ntp,技术|RHCE 系列(十):在 RHEL/CentOS 7 中设置 NTP(网络时间协议)服务器...
  7. python加载csv文件去重_用python读写和处理csv文件
  8. cp复制多个文件到指定目录
  9. js创建对象的七种方式
  10. linux c++ 输出到终端,如何将彩色文本输出到Linux终端?