Windows Server 安裝 RabbitMQ

今天準備做 Message Broker 的 POC。我想做的是,在兩台開發環境 VM 裝 RabbitMQ 來做基本的 cluster。正準備在內部開發環境上安裝 RabbitMQ ,但因為內網開發環境的資源已經將要用完。IT幫我查了一下,許多之前開的VM幾乎沒什麼使用率,遂表示不建議再生VM。建議我找之前開的VM來重複利用。

因為原來的VM都是 Windows Server 2012,所以下載了 RabbitMQ 的 Windows Distribution 與 OTP (Erlang) 準備安裝。

問題

安裝完以後遇上了小問題。我要使用 rabbitmqctl status 來查閱安裝結果的時候出現

Status of node rabbit@DEV03 ...
Error: unable to perform an operation on node 'rabbit@DEV03'. Please see diagnostics information and suggestions below.

Most common reasons for this are:

 * Target node is unreachable (e.g. due to hostname resolution, TCP connection o r firewall issues)
 * CLI tool fails to authenticate with the server (e.g. due to CLI tool's Erlang cookie not matching that of the server)
 * Target node is not running

In addition to the diagnostics info below:

 * See the CLI, clustering and networking guides on http://rabbitmq.com/documentation.html to learn more
 * Consult server logs on node rabbit@DEV03

接著 Rabbit 的診斷結果一看就知道有可能是 Magic Cookie 的問題

DIAGNOSTICS
===========

attempted to contact: [rabbit@DEV03]

rabbit@DEV03:
  * connected to epmd (port 4369) on DEV03
  * epmd reports node 'rabbit' uses port 25672 for inter-node and CLI tool traffic
  * TCP connection succeeded but Erlang distribution failed
  * Authentication failed (rejected by the remote node), please check the Erlang cookie

Current node details:
 * node name: rabbitmqcli40@DEV03
 * effective user's home directory: C:Usersalex
 * Erlang cookie hash: gK4zBWcnFKbA++Vp1Jl/jQ==

翻找了一下文件後,發現 RabbitMQ 下載頁面交代說安裝 OTP 時要用 Admin 權限。應該是因為在安裝 Erlang 的時候會建立一個 Erlang Magic Cookie 。這個 .erlang.cookie 檔案會被寫入 C:\Windows 資料夾內(%HOMEDRIVE%)。

RabbitMQ 官網有提到同步 Cookie 的問題,這邊的預設立場是,Erlang 安裝完以後,有建立起 .erlang.cookie 檔案。

Synchronise Erlang Cookies (when running a manually installed Windows Service)

Erlang Security Cookies used by the service account and the user running rabbitmqctl.bat must be synchronised for rabbitmqctl.bat to function.

To ensure Erlang cookie files contain the same string, copy the <span class="code ">.erlang.cookie</span> file from the Windows directory (normally <span class="code ">C:\WINDOWS.erlang.cookie</span>) to replace the user <span class="code ">.erlang.cookie</span>. The user cookie will be in the user's home directory (<span class="envvar">%HOMEDRIVE%</span><span class="envvar">%HOMEPATH%</span>), e.g. <span class="code ">C:\Documents and Settings<span class="envvar">%USERNAME%</span>.erlang.cookie</span>or <span class="code ">C:\Users<span class="envvar">%USERNAME%</span>.erlang.cookie</span> (Windows Vista and later).

但我在VM上的 C:\Windows 卻找不到 .erlang.cookie 檔案!只找到 C:\Users\%USERNAME%\.erlang.cookie 我想可能是因為我登入VM的時候用的是AD帳號,安裝時權限不足以在 C:\Windows 下寫入檔案。厄..只好去翻了翻 Erlang 的官網看看怎麼辦。解法找不到,倒是有看到關於魔術餅乾(Erlang Magic Cookie)的用途:


Authentication determines which nodes are allowed to communicate with each other. In a network of different Erlang nodes, it is built into the system at the lowest possible level. Each node has its own magic cookie, which is an Erlang atom.

然後有關於 Cookie 的產生:


At start-up, a node has a random atom assigned as its magic cookie and the cookie of other nodes is assumed to be nocookie. The first action of the Erlang network authentication server (auth) is then to read a file named $HOME/.erlang.cookie. If the file does not exist, it is created. The UNIX permissions mode of the file is set to octal 400 (read-only by user) and its contents are a random string. An atom Cookie is created from the contents of the file and the cookie of the local node is set to this usingerlang:set_cookie(node(), Cookie). This also makes the local node assume that all other nodes have the same cookie Cookie.

解法

琢磨了一下,我就直接把 C:\Users\%USERNAME%\.erlang.cookie 複製到 %HOMEDRIVE%。但問題仍然還是一樣

* Authentication failed (rejected by the remote node), please check the Erlang cookie

然後試了一下是不是 RabbitMQ 的 erlang node 吃不到 cookie,於是就用 erl shell 設定 runtime 的 rabbit (-sname rabbit) 的 cookie ,設的跟 %HOMEDRIVE% 下的一樣,然後連線就正常了!

C:\Windows\system32>"C:\Program Fileserl9.2\binerl.exe" -sname rabbit -setcookie SBAGGAVFWIPXEEDTLWA
Eshell V9.2 (abort with ^G)
(rabbit@DEV03)1> erlang:get_cookie().
'SBAGGAVFWIPXEEDTLWA'

想了一下,原來還是我沒想到是登入的帳號問題。我是用 AD 帳號登入安裝並的,RabbitMQ 的確是幫我在我建了一個 .erlang.cookie 檔案在我的 user 資料夾。但服務啟動的時候執行者是 local system account

rabbit-mq-windows-service-screen

我試了一下把執行服務的帳號改成我的AD帳號,重啟 RabbitMQ Service 再執行 rabbitmqctl status 就可以正常連線了!

看來,還是得乖乖建一個系統帳號給他使用才是。

另外,也可以透過設定 RabbitMQ 來給予 Erlang 付加參數

As an alternative, you can add the option “-setcookie value" in the RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS environment variable value:

RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-setcookie cookie-value"

但官方建議這個是比較不安全的做法。