RabbitMQ 簡介
以熟悉的電商場景為例,如果商品服務和訂單服務是兩個不同的微服務,在下單的過程中訂單服務需要調用商品服務進行扣庫存操作。按照傳統的方式,下單過程要等到調用完畢之后才能返回下單成功,如果網絡產生波動等原因使得商品服務扣庫存延遲或者失敗,會帶來較差的用戶體驗,如果在高並發的場景下,這樣的處理顯然是不合適的,那怎么進行優化呢?這就需要消息隊列登場了。
消息隊列提供一個異步通信機制,消息的發送者不必一直等待到消息被成功處理才返回,而是立即返回。消息中間件負責處理網絡通信,如果網絡連接不可用,消息被暫存於隊列當中,當網絡暢通的時候在將消息轉發給相應的應用程序或者服務,當然前提是這些服務訂閱了該隊列。如果在商品服務和訂單服務之間使用消息中間件,既可以提高並發量,又降低服務之間的耦合度。
RabbitMQ就是這樣一款我們苦苦追尋的消息隊列。RabbitMQ是一個開源的消息代理的隊列服務器,用來通過普通協議在完全不同的應用之間共享數據。
RabbitMQ 的特點
開源、性能優秀,速度快,穩定性保障提供可靠性消息投遞模式、返回模式與Spring AMQP完美整合,API豐富集群模式豐富,表達式配置,HA模式,鏡像隊列模型保證數據不丟失的前提做到高可靠性、可用性
RabbitMQ 典型應用場景
- 異步處理:把消息放入消息中間件中,等到需要的時候再去處理。
- 流量削峰:例如秒殺活動,在短時間內訪問量急劇增加,使用消息隊列,當消息隊列滿了就拒絕響應,跳轉到錯誤頁面,這樣就可以使得系統不會因為超負載而崩潰。
- 日志處理;(不過一般日志處理都使用Kafka這種消息隊列)
- 應用解耦:假設某個服務A需要給許多個服務(B、C、D)發送消息,當某個服務(例如B)不需要發送消息了,服務A需要改代碼再次部署;當新加入一個服務(服務E)需要服務A的消息的時候,也需要改代碼重新部署;另外服務A也要考慮其他服務掛掉,沒有收到消息怎么辦?要不要重新發送呢?是不是很麻煩,使用MQ發布訂閱模式,服務A只生產消息發送到MQ,B、C、D從MQ中讀取消息,需要A的消息就訂閱,不需要了就取消訂閱,服務A不再操心其他的事情,使用這種方式可以降低服務或者系統之間的耦合。
RabbitMQ集群節點之間是如何相互認證的:
- 通過Erlang Cookie,相當於共享秘鑰的概念,長度任意,只要所有節點都一致即可。
- rabbitmq server在啟動的時候,erlang VM會自動創建一個隨機的cookie文件。cookie文件的位置是/var/lib/rabbitmq/.erlang.cookie 或者 /root/.erlang.cookie,為保證cookie的完全一致,采用從一個節點copy的方式。
Erlang Cookie是保證不同節點可以相互通信的密鑰,要保證集群中的不同節點相互通信必須共享相同的Erlang Cookie。具體的目錄存放在/var/lib/rabbitmq/.erlang.cookie。
說明:這就要從rabbitmqctl命令的工作原理說起,RabbitMQ底層是通過Erlang架構來實現的,所以rabbitmqctl會啟動Erlang節點,並基於Erlang節點來使用Erlang系統連接RabbitMQ節點,在連接過程中需要正確的Erlang Cookie和節點名稱,Erlang節點通過交換Erlang Cookie以獲得認證。
RabbitMQ集群模式
- 單機模式
- 普通集群模式(無高可用性)
- 鏡像集群模式(高可用性),最常用的集群模式。
RabbitMQ集群故障處理機制:
- rabbitmq broker集群允許個體節點down機,
- 對應集群的的網絡分區問題( network partitions)
RabbitMQ集群推薦用於LAN環境,不適用WAN環境;
要通過WAN連接broker,Shovel or Federation插件是最佳的解決方案;Shovel or Federation不同於集群。
RabbitMQ節點類型
- RAM node:只保存狀態到內存。內存節點將所有的隊列、交換機、綁定、用戶、權限和vhost的元數據定義存儲在內存中,好處是可以使得像交換機和隊列聲明等操作更加的快速。
- Disk node:將元數據存儲在磁盤中。單節點系統只允許磁盤類型的節點,防止重啟RabbitMQ的時候,丟失系統的配置信息。
內存節點雖然不寫入磁盤,但是它執行比磁盤節點要好。RabbitMQ集群中,只需要一個磁盤節點來保存狀態就足夠了;如果集群中只有內存節點,那么不能停止它們,否則所有的狀態,消息等都會丟失。
問題說明:
- RabbitMQ要求在集群中至少有一個磁盤節點,所有其他節點可以是內存節點,當節點加入或者離開集群時,必須要將該變更通知到至少一個磁盤節點。
- 如果集群中唯一的一個磁盤節點崩潰的話,集群仍然可以保持運行,但是無法進行其他操作(增刪改查),直到節點恢復。
解決方案:設置兩個磁盤節點,至少有一個是可用的,可以保存元數據的更改。
RabbitMQ集群的節點運行模式:
- 為保證數據持久性,當前所有node節點跑在disk模式。
- 如果今后壓力大,需要提高性能,考慮采用ram模式。
RabbitMQ集群記錄
本案例采用 "鏡像模式",即隊列為鏡像隊列,隊列消息存在集群的每個節點上。
1、版本說明
因為考慮到較早版本rabbitmq在k8s上的集群部署是使用autocluster插件去調用kubernetes apiserver來獲取rabbitmq服務的endpoints,進而獲取node節點信息,並自動加入集群,但是現在autocluster已不再更新了,並且只支持3.6.x版本,故而放棄這種方式。
對於3.7.x或更新的版本,現在市場主流是使用 peer discovery subsystem來構建rabbitmq-cluster,
參考這里。
2、部署方式
在Kubernetes上搭建RabbitMQ有4種部署方法(IP模式、Pod與Server的DNS模式、Statefulset 與Headless Service模式、hostname模式),這里選擇StatefulSet與Headless Service模式部署有狀態的RabbitMQ集群。
3、使用NFS配置StatefulSet的動態持久化存儲
1)在NFS服務器端(172.16.60.238)通過nfs創建RabbitMQ集群的共享目錄
[root@k8s-harbor01 ~]# mkdir -p /data/storage/k8s/rabbitmq
2)創建nfs的rbac
[root@k8s-master01 ~]# mkdir -p /opt/k8s/k8s_project/rabbitmq [root@k8s-master01 ~]# cd /opt/k8s/k8s_project/rabbitmq [root@k8s-master01 rabbitmq]# vim nfs-rbac.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: nfs-provisioner namespace: wiseco --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-provisioner-runner namespace: wiseco rules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["watch", "create", "update", "patch"] - apiGroups: [""] resources: ["services", "endpoints"] verbs: ["get","create","list", "watch","update"] - apiGroups: ["extensions"] resources: ["podsecuritypolicies"] resourceNames: ["nfs-provisioner"] verbs: ["use"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-provisioner subjects: - kind: ServiceAccount name: nfs-provisioner namespace: wiseco roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io
查看並創建
[root@k8s-master01 rabbitmq]# kubectl apply -f nfs-rbac.yaml serviceaccount/nfs-provisioner created clusterrole.rbac.authorization.k8s.io/nfs-provisioner-runner created clusterrolebinding.rbac.authorization.k8s.io/run-nfs-provisioner created [root@k8s-master01 rabbitmq]# kubectl get sa -n wiseco|grep nfs nfs-provisioner 1 6h2m [root@k8s-master01 rabbitmq]# kubectl get clusterrole -n wiseco|grep nfs nfs-provisioner-runner 2021-02-07T03:30:56Z [root@k8s-master01 rabbitmq]# kubectl get clusterrolebinding -n wiseco|grep nfs run-nfs-provisioner ClusterRole/nfs-provisioner-runner 6h2m
3)創建RabbitMQ集群的storageclass
[root@k8s-master01 rabbitmq]# ll total 4 -rw-r--r-- 1 root root 1216 Feb 7 17:33 nfs-rbac.yaml [root@k8s-master01 rabbitmq]# vim rabbitmq-nfs-class.yaml apiVersion: storage.k8s.io/v1beta1 kind: StorageClass metadata: name: rabbitmq-nfs-storage namespace: wiseco provisioner: rabbitmq/nfs reclaimPolicy: Retain
查看並創建
[root@k8s-master01 rabbitmq]# kubectl apply -f rabbitmq-nfs-class.yaml storageclass.storage.k8s.io/rabbitmq-nfs-storage created [root@k8s-master01 rabbitmq]# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE rabbitmq-nfs-storage rabbitmq/nfs Retain Immediate false 3s
4)創建MongoDB集群的nfs-client-provisioner
[root@k8s-master01 rabbitmq]# ll total 8 -rw-r--r-- 1 root root 1216 Feb 7 17:33 nfs-rbac.yaml -rw-r--r-- 1 root root 161 Feb 7 17:37 rabbitmq-nfs-class.yaml [root@k8s-master01 rabbitmq]# vim rabbitmq-nfs.yml apiVersion: apps/v1 kind: Deployment metadata: name: rabbitmq-nfs-client-provisioner namespace: wiseco spec: replicas: 1 selector: matchLabels: app: rabbitmq-nfs-client-provisioner strategy: type: Recreate template: metadata: labels: app: rabbitmq-nfs-client-provisioner spec: serviceAccount: nfs-provisioner containers: - name: rabbitmq-nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner imagePullPolicy: IfNotPresent volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: rabbitmq/nfs - name: NFS_SERVER value: 172.16.60.238 - name: NFS_PATH value: /data/storage/k8s/rabbitmq volumes: - name: nfs-client-root nfs: server: 172.16.60.238 path: /data/storage/k8s/rabbitmq
查看並創建
[root@k8s-master01 rabbitmq]# kubectl apply -f rabbitmq-nfs.yml deployment.apps/rabbitmq-nfs-client-provisioner created [root@k8s-master01 rabbitmq]# kubectl get pods -n wiseco|grep rabbitmq rabbitmq-nfs-client-provisioner-c4f95d479-xvm8r 1/1 Running 0 17s
4、部署RabbitMQ基於鏡像模式的集群
[root@k8s-master01 rabbitmq]# ll total 12 -rw-r--r-- 1 root root 1216 Feb 7 17:33 nfs-rbac.yaml -rw-r--r-- 1 root root 161 Feb 7 17:37 rabbitmq-nfs-class.yaml -rw-r--r-- 1 root root 1027 Feb 7 17:46 rabbitmq-nfs.yml [root@k8s-master01 rabbitmq]# mkdir deployment [root@k8s-master01 rabbitmq]# cd deployment [root@k8s-master01 deployment]#
采用StatefulSet與Headless Service模式部署有狀態的RabbitMQ集群。
rabbitmq.yml文件內容:
[root@k8s-master01 deployment]# vim rabbitmq.yml --- apiVersion: v1 kind: Service metadata: name: rabbitmq-management namespace: wiseco labels: app: rabbitmq spec: ports: - port: 15672 name: http selector: app: rabbitmq type: NodePort --- apiVersion: v1 kind: Service metadata: name: rabbitmq namespace: wiseco labels: app: rabbitmq spec: ports: - port: 5672 name: amqp - port: 4369 name: epmd - port: 25672 name: rabbitmq-dist clusterIP: None selector: app: rabbitmq --- apiVersion: apps/v1 kind: StatefulSet metadata: namespace: wiseco name: rabbitmq spec: serviceName: "rabbitmq" replicas: 3 selector: matchLabels: app: rabbitmq template: metadata: labels: app: rabbitmq spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - rabbitmq topologyKey: "kubernetes.io/hostname" containers: - name: rabbitmq image: rabbitmq:3.7-rc-management lifecycle: postStart: exec: command: - /bin/sh - -c - > if [ -z "$(grep rabbitmq /etc/resolv.conf)" ]; then sed "s/^search \([^ ]\+\)/search rabbitmq.\1 \1/" /etc/resolv.conf > /etc/resolv.conf.new; cat /etc/resolv.conf.new > /etc/resolv.conf; rm /etc/resolv.conf.new; fi; until rabbitmqctl node_health_check; do sleep 1; done; if [ -z "$(rabbitmqctl cluster_status | grep rabbitmq-0)" ]; then touch /gotit rabbitmqctl stop_app; rabbitmqctl reset; rabbitmqctl join_cluster rabbit@rabbitmq-0; rabbitmqctl start_app; else touch /notget fi; env: - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: RABBITMQ_ERLANG_COOKIE value: "YZSDHWMFSMKEMBDHSGGZ" - name: RABBITMQ_NODENAME value: "rabbit@$(MY_POD_NAME)" ports: - name: http protocol: TCP containerPort: 15672 - name: amqp protocol: TCP containerPort: 5672 livenessProbe: tcpSocket: port: amqp initialDelaySeconds: 5 timeoutSeconds: 5 periodSeconds: 10 readinessProbe: tcpSocket: port: amqp initialDelaySeconds: 15 timeoutSeconds: 5 periodSeconds: 20 volumeMounts: - name: rabbitmq-data mountPath: /var/lib/rabbitmq volumeClaimTemplates: - metadata: name: rabbitmq-data annotations: volume.beta.kubernetes.io/storage-class: "rabbitmq-nfs-storage" spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi
查看並創建
[root@k8s-master01 deployment]# kubectl apply -f rabbitmq.yml service/rabbitmq-management created service/rabbitmq created statefulset.apps/rabbitmq created [root@k8s-master01 deployment]# kubectl get pods -n wiseco -o wide|grep rabbitmq rabbitmq-0 1/1 Running 0 11m 172.30.85.206 k8s-node01 <none> <none> rabbitmq-1 1/1 Running 0 9m9s 172.30.217.69 k8s-node04 <none> <none> rabbitmq-2 1/1 Running 0 7m59s 172.30.135.145 k8s-node03 <none> <none> rabbitmq-nfs-client-provisioner-c4f95d479-xvm8r 1/1 Running 0 20h 172.30.217.122 k8s-node04 <none> <none> [root@k8s-master01 deployment]# kubectl get svc -n wiseco|grep rabbitmq rabbitmq ClusterIP None <none> 5672/TCP,4369/TCP,25672/TCP 8m27s rabbitmq-management NodePort 10.254.128.136 <none> 15672:32513/TCP 8m27s
查看PV、PVC
[root@k8s-master01 deployment]# kubectl get pvc -n wiseco NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE rabbitmq-data-rabbitmq-0 Bound pvc-19579da4-fe40-4cc5-abb5-670486cc3f12 10Gi RWX rabbitmq-nfs-storage 9m38s rabbitmq-data-rabbitmq-1 Bound pvc-13218c20-2a79-40f2-92fa-a18300729c12 10Gi RWX rabbitmq-nfs-storage 7m5s rabbitmq-data-rabbitmq-2 Bound pvc-7a13561a-1d9c-430c-90df-45ccad455fce 10Gi RWX rabbitmq-nfs-storage 5m55s [root@k8s-master01 deployment]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-13218c20-2a79-40f2-92fa-a18300729c12 10Gi RWX Delete Bound wiseco/rabbitmq-data-rabbitmq-1 rabbitmq-nfs-storage 7m3s pvc-19579da4-fe40-4cc5-abb5-670486cc3f12 10Gi RWX Delete Bound wiseco/rabbitmq-data-rabbitmq-0 rabbitmq-nfs-storage 9m38s pvc-7a13561a-1d9c-430c-90df-45ccad455fce 10Gi RWX Delete Bound wiseco/rabbitmq-data-rabbitmq-2 rabbitmq-nfs-storage 5m55s
查看NFS共享存儲
NFS服務器(172.16.60.238),查看共享目錄/data/storage/k8s/rabbitmq
[root@k8s-harbor01 ~]# cd /data/storage/k8s/rabbitmq/ [root@k8s-harbor01 rabbitmq]# ll total 0 drwxrwxrwx 5 polkitd root 70 Feb 8 14:17 wiseco-rabbitmq-data-rabbitmq-0-pvc-19579da4-fe40-4cc5-abb5-670486cc3f12 drwxrwxrwx 5 polkitd root 70 Feb 8 14:19 wiseco-rabbitmq-data-rabbitmq-1-pvc-13218c20-2a79-40f2-92fa-a18300729c12 drwxrwxrwx 5 polkitd root 70 Feb 8 14:21 wiseco-rabbitmq-data-rabbitmq-2-pvc-7a13561a-1d9c-430c-90df-45ccad455fce [root@k8s-harbor01 rabbitmq]# ls ./* ./wiseco-rabbitmq-data-rabbitmq-0-pvc-19579da4-fe40-4cc5-abb5-670486cc3f12: config mnesia schema ./wiseco-rabbitmq-data-rabbitmq-1-pvc-13218c20-2a79-40f2-92fa-a18300729c12: config mnesia schema ./wiseco-rabbitmq-data-rabbitmq-2-pvc-7a13561a-1d9c-430c-90df-45ccad455fce: config mnesia schema 查看RabbitMQ的三個容器節點的.erlang.cookie,內容是一致的! [root@k8s-harbor01 rabbitmq]# ll ./*/.erlang.cookie -rw------- 1 polkitd input 21 Feb 8 14:16 ./wiseco-rabbitmq-data-rabbitmq-0-pvc-19579da4-fe40-4cc5-abb5-670486cc3f12/.erlang.cookie -rw------- 1 polkitd input 21 Feb 8 14:19 ./wiseco-rabbitmq-data-rabbitmq-1-pvc-13218c20-2a79-40f2-92fa-a18300729c12/.erlang.cookie -rw------- 1 polkitd input 21 Feb 8 14:20 ./wiseco-rabbitmq-data-rabbitmq-2-pvc-7a13561a-1d9c-430c-90df-45ccad455fce/.erlang.cookie [root@k8s-harbor01 rabbitmq]# cat ./*/.erlang.cookie YZSDHWMFSMKEMBDHSGGZ YZSDHWMFSMKEMBDHSGGZ YZSDHWMFSMKEMBDHSGGZ
5、驗證RabbitMQ集群
進入RabbitMQ集群節點Pod容器,查看RabbitMQ集群狀態(三個Pod查看的集群狀態是一樣的)
登錄rabbitmq-0容器查看集群狀態 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl cluster_status Cluster status of node rabbit@rabbitmq-0 ... [{nodes,[{disc,['rabbit@rabbitmq-0','rabbit@rabbitmq-1', 'rabbit@rabbitmq-2']}]}, {running_nodes,['rabbit@rabbitmq-2','rabbit@rabbitmq-1','rabbit@rabbitmq-0']}, {cluster_name,<<"rabbit@rabbitmq-0.rabbitmq.wiseco.svc.cluster.local">>}, {partitions,[]}, {alarms,[{'rabbit@rabbitmq-2',[]}, {'rabbit@rabbitmq-1',[]}, {'rabbit@rabbitmq-0',[]}]}] 登錄rabbitmq-1容器查看集群狀態 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-1 -n wiseco -- rabbitmqctl cluster_status Cluster status of node rabbit@rabbitmq-1 ... [{nodes,[{disc,['rabbit@rabbitmq-0','rabbit@rabbitmq-1', 'rabbit@rabbitmq-2']}]}, {running_nodes,['rabbit@rabbitmq-2','rabbit@rabbitmq-0','rabbit@rabbitmq-1']}, {cluster_name,<<"rabbit@rabbitmq-0.rabbitmq.wiseco.svc.cluster.local">>}, {partitions,[]}, {alarms,[{'rabbit@rabbitmq-2',[]}, {'rabbit@rabbitmq-0',[]}, {'rabbit@rabbitmq-1',[]}]}] 登錄rabbitmq-2容器查看集群狀態 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-2 -n wiseco -- rabbitmqctl cluster_status Cluster status of node rabbit@rabbitmq-2 ... [{nodes,[{disc,['rabbit@rabbitmq-0','rabbit@rabbitmq-1', 'rabbit@rabbitmq-2']}]}, {running_nodes,['rabbit@rabbitmq-0','rabbit@rabbitmq-1','rabbit@rabbitmq-2']}, {cluster_name,<<"rabbit@rabbitmq-0.rabbitmq.wiseco.svc.cluster.local">>}, {partitions,[]}, {alarms,[{'rabbit@rabbitmq-0',[]}, {'rabbit@rabbitmq-1',[]}, {'rabbit@rabbitmq-2',[]}]}]
6、訪問RabbitMQ的Web界面,查看集群狀態
[root@k8s-master01 deployment]# kubectl get svc -n wiseco|grep rabbitmq rabbitmq ClusterIP None <none> 5672/TCP,4369/TCP,25672/TCP 23m rabbitmq-management NodePort 10.254.128.136 <none> 15672:32513/TCP 23m
通過K8S的node節點的32513訪問web頁面,用戶名和密碼都是guest

7、RabbitMQ的日常操作命令
1)用戶管理 ===================================================================================================== 新增一個用戶 # rabbitmqctl add_user Username Password 刪除一個用戶 # rabbitmqctl delete_user Username 修改用戶的密碼 # rabbitmqctl change_password Username Newpassword 查看當前用戶列表 # rabbitmqctl list_users 比如:修改guest用戶密碼、新增或刪除一個用戶 查看當前用戶列表 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl list_users Listing users ... user tags guest [administrator] 修改guest用戶密碼為 guest@123 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl change_password guest guest@123 Changing password for user "guest" .. 新增一個用戶,用戶名為kevin,密碼為 kevin@123 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl add_user kevin kevin@123 Adding user "kevin" ... 查看當前用戶列表 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl list_users Listing users ... user tags guest [administrator] kevin [] 設置kevin用戶角色為administrator [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl set_user_tags kevin administrator Setting tags for user "kevin" to [administrator] ... 查看當前用戶列表 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl list_users Listing users ... user tags guest [administrator] kevin [administrator] 修改kevin用戶角色為monitoring、policymaker [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl set_user_tags kevin monitoring policymaker Setting tags for user "kevin" to [monitoring, policymaker] ... 查看當前用戶列表 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl list_users Listing users ... user tags guest [administrator] kevin [monitoring, policymaker] 刪除kevin用戶 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl delete_user kevin Deleting user "kevin" ... 查看當前用戶列表 [root@k8s-master01 deployment]# kubectl exec -ti rabbitmq-0 -n wiseco -- rabbitmqctl list_users Listing users ... user tags guest [administrator] 2)用戶角色 ===================================================================================================== 用戶角色分類 用戶角色可分為五類:超級管理員、監控者、策略制定者、普通管理者以及其他。 超級管理員 (administrator) 可登陸管理控制台(啟用management plugin的情況下),可查看所有的信息,並且可以對用戶,策略(policy)進行操作。 監控者 (monitoring) 可登陸管理控制台(啟用management plugin的情況下),同時可以查看rabbitmq節點的相關信息(進程數,內存使用情況,磁盤使用情況等) 策略制定者 (policymaker) 可登陸管理控制台(啟用management plugin的情況下), 同時可以對policy進行管理。但無法查看節點的相關信息 普通管理者 (management) 僅可登陸管理控制台(啟用management plugin的情況下),無法看到節點信息,也無法對策略進行管理。 其他 無法登陸管理控制台,通常就是普通的生產者和消費者。 相關操作命令: 設置用戶角色的命令為: # rabbitmqctl set_user_tags User Tag 其中: User為用戶名 Tag為角色名 (對應於上面的administrator,monitoring,policymaker,management,或其他自定義名稱)。 也可以給同一用戶設置多個角色,例如: # rabbitmqctl set_user_tags kevin monitoring policymaker 3)用戶權限 ===================================================================================================== 用戶權限指的是用戶對exchange,queue的操作權限,包括配置權限,讀寫權限。 配置權限會影響到exchange,queue的聲明和刪除。 讀寫權限影響到從queue里取消息,向exchange發送消息以及queue和exchange的綁定(bind)操作。 例如: 將queue綁定到某exchange上,需要具有queue的可寫權限,以及exchange的可讀權限; 向exchange發送消息需要具有exchange的可寫權限; 從queue里取數據需要具有queue的可讀權限。 相關操作命令: 設置用戶權限 # rabbitmqctl set_permissions -p VHostPath User ConfP WriteP ReadP 查看(指定hostpath)所有用戶的權限信息 # rabbitmqctl list_permissions [-p VHostPath] 查看指定用戶的權限信息 # rabbitmqctl list_user_permissions User 清除用戶的權限信息 # rabbitmqctl clear_permissions [-p VHostPath] User 設置節點類型 RabbitMQ節點類型分為內存節點和硬盤節點。 如果你想更換節點類型可以通過命令修改: # rabbitmqctl stop_app # rabbitmqctl change_cluster_node_type dist # rabbitmqctl change_cluster_node_type ram # rabbitmqctl start_app
8、模擬RabbitMQ節點故障
模擬故障,重啟其中的一個node節點,比如rabbitmq-0,然后觀察集群狀態:
[root@k8s-master01 deployment]# kubectl get pods -n wiseco -o wide|grep rabbitmq rabbitmq-0 1/1 Running 0 71m 172.30.85.206 k8s-node01 <none> <none> rabbitmq-1 1/1 Running 0 68m 172.30.217.69 k8s-node04 <none> <none> rabbitmq-2 1/1 Running 0 67m 172.30.135.145 k8s-node03 <none> <none> rabbitmq-nfs-client-provisioner-c4f95d479-xvm8r 1/1 Running 0 21h 172.30.217.122 k8s-node04 <none> <none> 刪除rabbitmq-0節點 [root@k8s-master01 deployment]# kubectl delete pods rabbitmq-0 -n wiseco pod "rabbitmq-0" deleted 查看pod,發現rabbitmq-0節點刪除后,重啟需要耗費一段時間 [root@k8s-master01 deployment]# kubectl get pods -n wiseco -o wide|grep rabbitmq rabbitmq-0 0/1 ContainerCreating 0 44s <none> k8s-node01 <none> <none> rabbitmq-1 1/1 Running 0 70m 172.30.217.69 k8s-node04 <none> <none> rabbitmq-2 1/1 Running 0 69m 172.30.135.145 k8s-node03 <none> <none> rabbitmq-nfs-client-provisioner-c4f95d479-xvm8r 1/1 Running 0 21h 172.30.217.122 k8s-node04 <none> <none> 此時,查看RabbitMQ集群狀態 發現此時,rabbit@rabbitmq-0節點還沒有恢復,running的node節點只有rabbit@rabbitmq-2、rabbit@rabbitmq-1 [root@k8s-master01 ~]# kubectl exec -ti rabbitmq-1 -n wiseco -- rabbitmqctl cluster_status Cluster status of node rabbit@rabbitmq-1 ... [{nodes,[{disc,['rabbit@rabbitmq-0','rabbit@rabbitmq-1', 'rabbit@rabbitmq-2']}]}, {running_nodes,['rabbit@rabbitmq-2','rabbit@rabbitmq-1']}, {cluster_name,<<"rabbit@rabbitmq-0.rabbitmq.wiseco.svc.cluster.local">>}, {partitions,[]}, {alarms,[{'rabbit@rabbitmq-2',[]},{'rabbit@rabbitmq-1',[]}]}]
此時,查看web界面的集群狀態,先后經歷了下面三個狀態:
- 紅色表示 節點故障。
- 黃色表示 節點恢復中,暫不可用。
- 綠色表示 點運行正常。

9、客戶端訪問RabbitMQ集群地址
客戶端連接RabbitMQ集群地址:rabbitmq-0.rabbitmq.wiseco.svc.cluster.local:5672、rabbitmq-0.rabbitmq.wiseco.svc.cluster.local:5672、rabbitmq-0.rabbitmq.wiseco.svc.cluster.local:5672
連接方式:
- 客戶端可以連接RabbitMQ集群中的任意一個節點。如果一個節點故障,客戶端自行重新連接到其他的可用節點;
- 也就是說,RabbitMQ集群有"重連"機制,但是這種集群連接方式對客戶端不透明,不太建議這種連接方式。
推薦方式:給客戶端提供一個統一的透明的集群連接地址
做法:在前面部署LVS或Haproxy,通過四層負載均衡代理后RabbitMQ的三個node節點的5672端口。