RabbitMQ運維

這是一次比較苦逼的運維,完全不熟悉的系統、不清楚環境、不清楚配置,兩眼一抹黑。爲啥?就是因爲原來的負責人撤了、交接人休假、再次交接人也休假,再再次交接人只有一份不全的文檔。而我是再、再、再次交接人,連文檔也沒有。更要命的是,這是生產環境,大家都懂得,生產環境就是不能出問題,自封一個“奉命於危難之間”吧。

抱怨了一整段了,還是簡單的說下這次運維吧,運維的是RabbitMQ集羣,3個節點A、B、C,每個節點上啓動了2個實例a1/a2、b1/b2、c1/c2,其中a1、b1、c1組成一套集羣環境rabbit cluster1,a1是磁盤節點;a2、b2、c2組成一套集羣環境rabbit cluster2,c2是磁盤節點。

就是因爲完全不熟悉RabbitMQ集羣,所以基本上趟了一堆的坑,碰到了一堆不應該出現的錯誤,也算是新手村長經驗了。按照套路,這裏先說說正確的啓動方式,然後再說說碰到的異常。

1. 正確啓動

1.1 啓動各個節點

因爲找不到自己啓動的歷史了,就是摘取官網的部分內容放在這裏。有3個服務器節點,hostname分別是:rabbit1、rabbit2、rabbit3。

分別在3個節點上啓動Rabbit MQ:

rabbit1$ rabbitmq-server -detached

rabbit2$ rabbitmq-server -detached

rabbit3$ rabbitmq-server -detached

通過命令rabbitmq-server -detached就可以啓動rabbit服務。

然後在每個節點上查看集羣狀態:

rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1]}]},{running_nodes,[rabbit@rabbit1]}]
...done.

rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit2]}]},{running_nodes,[rabbit@rabbit2]}]
...done.

rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ...
[{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}]
...done.

RabbitMQ服務節點的名字是rabbit@shorthostname,所以上面3個節點分別是rabbit@rabbit1、rabbit@rabbit2、rabbit@rabbit3。需要注意的是使用rabbitmq-server基本執行的名字都是小寫的,如果是在Windows中使用rabbitmq-server.bat,那節點名字就是大寫的了,比如rabbit@RABBIT1。

1.2 創建集羣

這裏把rabbit@rabbit2和rabbit@rabbit3加入rabbit@rabbit1中,也就是說rabbit@rabbit1是磁盤節點,其他兩個都是內存節點。

先把rabbit@rabbit2加入到rabbit@rabbit1中:

rabbit2$ rabbitmqctl stop_app
Stopping node rabbit@rabbit2 ...done.

rabbit2$ rabbitmqctl join_cluster rabbit@rabbit1
Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.

rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.

如果沒有報錯,rabbit@rabbit2就已經加入到rabbit@rabbit1中了,可以使用命令rabbitmqctl cluster_status查看集羣狀態:

rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.

rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}]
...done.

通過join_cluster --ram可以指定節點以內存節點的形式加入集羣。然後在rabbit@rabbit3上執行相同的操作即可,這裏不再贅述。

1.3 拆分集羣

拆分集羣實際上就是在想要從集羣中刪除的節點上執行reset即可,他會通知集羣中所有的節點不要再理這個節點了。

rabbit3$ rabbitmqctl stop_app
Stopping node rabbit@rabbit3 ...done.

rabbit3$ rabbitmqctl reset
Resetting node rabbit@rabbit3 ...done.

rabbit3$ rabbitmqctl start_app
Starting node rabbit@rabbit3 ...done.

在各個節點上查看集羣狀態:

rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.

rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}]
...done.

rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ...
[{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}]
...done.

還可以在某節點上刪除別的節點,可以使用forget_cluster_node來進行,這裏不進行贅述,後面的一種異常中會用到這個命令。

2. 幾個異常

2.1 一臺機器上啓動多個實例

RabbitMQ允許在一臺機器上啓動多個實例,自己在這次運維中佔用時間最長的就是不知道這3個節點上部署了兩套集羣,通過ps -ef|grep rabbit命令看到有兩個實例,就天真的以爲是有一個沒有成功關閉,所以直接把兩個都kill了。所以這裏記錄一下如果在一臺機器上啓動多個實例。

$ RABBITMQ_NODE_PORT=5673 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15673}]" RABBITMQ_NODENAME=hare rabbitmq-server -detached
$ rabbitmqctl -n hare stop_app
$ rabbitmqctl -n hare join_cluster rabbit@rabbit1
$ rabbitmqctl -n hare start_app

執行命令需要使用-n來指定執行命令的實例,這個是需要記住的。

2.2 Bad cookie in table definition rabbit_durable_queue

這個已經找不到錯誤的具體描述了,就從Google上找了一條,基本類似。

rabbitmqctl cluster rabbit@vmrabbita
Clustering node rabbit@vmrabbitb with [rabbit@vmrabbita] ...
Error: {unable_to_join_cluster,
          [rabbit@vmrabbita],
          {merge_schema_failed,
              "Bad cookie in table definition rabbit_durable_queue: rabbit@vmrabbitb = {cstruct,rabbit_durable_queue,set,[],[rabbit@vmrabbitb],[],0,read_write,[],[],false,amqqueue,[name,durable,auto_delete,arguments,pid],[],[],{{1266,16863,365586},rabbit@vmrabbitb},{{2,0},[]}}, rabbit@vmrabbita = {cstruct,rabbit_durable_queue,set,[],[rabbit@vmrabbitc,rabbit@vmrabbita],[],0,read_write,[],[],false,amqqueue,[name,durable,auto_delete,arguments,pid],[],[],{{1266,14484,94839},rabbit@vmrabbita},{{4,0},{rabbit@vmrabbitc,{1266,16151,144423}}}}\n"}}

主要的就是Bad cookie in table definition rabbit_durable_queue這句,這是因爲節點之間是通過“the Erlang Cookie”彼此識別的,存儲在$HOME/.erlang.cookie中。如果因爲某種原因,集羣中幾個節點服務器上的cookie不一致,就會不能夠彼此識別,出現這樣那樣的錯誤。更多的是上面的這個"Bad cookie。。。",還會有"Connection attempt from disallowed node"、 “Could not auto-cluster”。

2.3 already_member

這個問題就是比較2的一個問題了,自己給自己挖的坑,只能自己填了。集羣幾個節點之間不能通信,然後我就把一個內存節點的var/lib/rabbitmq/mnesia中的文件夾刪了,然後又執行了reset,當執行join_cluster命令的時候,就會報出錯誤:

Error: {ok,already_member}

分析一下可以明白,當前節點上沒有待加入集羣的信息,但是待加入集羣中已經有了該節點的信息,但是發現兩個信息不一致。所以噹噹前節點期望加入到集羣的時候,出於安全考慮,集羣就說你小子已經是集羣裏的一員了,不要再加了。扒出日誌來看:

=INFO REPORT==== 25-Jul-2016::20:11:10 ===
Error description:
   {could_not_start,rabbitmq_management,
       {{shutdown,
            {failed_to_start_child,rabbit_mgmt_sup,
                {'EXIT',
                    {{shutdown,
                         [{{already_started,<23251.1658.0>},
                           {child,undefined,rabbit_mgmt_db,
                               {rabbit_mgmt_db,start_link,[]},
                               permanent,4294967295,worker,
                               [rabbit_mgmt_db]}}]},
                     {gen_server2,call,
                         [<0.618.0>,{init,<0.616.0>},infinity]}}}}},
        {rabbit_mgmt_app,start,[normal,[]]}}}

Log files (may contain more information):
   ./../var/log/rabbitmq/hare.log
   ./../var/log/rabbitmq/hare-sasl.log

既然集羣中已經有個該節點信息,所以不要該節點重複加入。那就把集羣裏該節點信息刪了,再加入集羣,不就應該類似與一個全新的節點加入集羣一樣嗎?

rabbitmqctl -n hare forget_cluster_node hare@rabbit1

這樣,集羣中就沒有hare@rabbit1的信息了,之後就重新執行join_cluster命令即可。

2.4 千萬不要在磁盤節點上刪除var/lib/rabbitmq/mnesia中的文件

這個文件夾中的內容是磁盤節點用於記錄集羣信息的文件,一旦刪除,會出現各種各樣的異常。

  1. 如果是磁盤節點,集羣中配置的Exchanges、Queues、User等信息全都丟失
  2. 如果是內存節點,連接集羣的信息丟失,重新加入集羣是會失敗

因爲是兩套集羣,這兩個問題我都碰到了。生產環境啊,可以想象當我正在爲集羣正常啓動後得意的時候,突然發現所有的Exchanges、Queues信息全都沒了的時候的心情嗎?幸虧還有一套預生產環境,直接把預生產環境的內容導出,然後在生產環境導入。

唉,有種劫後餘生的感動。。。


個人主頁: http://www.howardliu.cn

個人博文: RabbitMQ運維

CSDN主頁: http://blog.csdn.net/liuxinghao

CSDN博文: RabbitMQ運維

發佈了77 篇原創文章 · 獲贊 95 · 訪問量 52萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章