rabbitmq起源於Advanced Message Queuing Protocol(AMQP,高級消息隊列協議,參見 [AMQP-wiki]),AMQP從一開始就設計成爲開放標準,以解決衆多的消息隊列需求和拓撲結構問題。憑藉開放,任何人均可以執行這一標準,針對標準編碼的任何人均可以和任意AMQP供應商提供的MQ服務器進行交互。AMQP解決分佈式環境下的通訊問題,而Erlang是最適合實現AMQP代理服務器的語言,由於AMQP展示的就是每一部電話交換機的架構,Erlang是Ericson(愛立信)本來爲了電話交換機而開發的編程語言,其分佈式編程和健壯的故障恢復的特點特別適合AMQP。因爲rabbitmq的核心開發人員使用Erlang寫了一個原型測試網絡延遲,發現用Erlang編寫的分佈式計算庫和原生socket擁有同樣的延遲,因而他們決定起名爲Rabbit:兔子行動很是迅速且繁殖瘋狂,特別適合分佈式軟件的命名,也便於記憶。rabbitmq解決了只有少許預算同時也要須要消息通訊的問題,解決了應用集成和高強度事務處理負載的問題。現在,不少技術公司和金融公司都在使用rabbitmq,官方頁面有至關豐富的文檔,github上面也有不少rabbitmq的例子,客戶端有各類版本,好比lisp,.net,elixir,erlang,go,haskell,java,js,objective-c,perl,php,python,ruby,swift等。本文旨在幫助初學者搭建rabbitmq的環境,而後跑一個erlang的客戶端例子,算是入門。(我本身按照網上其餘人的例子還有官網的例子,沒能正常跑起來,即使是對照《RabbitMQ實戰-高效部署分佈式消息隊列》這本書抄的python代碼,都曲折無比,不能正常跑起來。因此將遇到的一些坑記錄下來,但願能減小後來者的時間。)php
rabbitmq是一個訂閱-發佈的消息隊列,生產者生成數據,發往rabbitmq,消費者根據訂閱,消費生產者的消息。html
個人rabbitmq是安裝在linux環境下的,erlang客戶端能夠跑在linux下,也能夠跑在windows下。java
tar -xvf rabbitmq-server-generic-unix-3.6.12.tar.xz解壓以後會產生rabbitmq_server - 3.6.12目錄,rabbitmq-server是免安裝的,解壓以後就立馬能用了,直接運行命令就能跑起來了
rabbitmq_server-3.6.12/sbin/rabbitmq-server若是要後臺啓動,能夠加"-detached"參數
rabbitmq_server-3.6.12/sbin/rabbitmq-server -detached關於rabbitmq的命令,能夠參考這個:RabbitMQ經常使用命令。若是讀者以爲每次都輸入路徑很麻煩,能夠把rabbitmq-server這個可執行文件拷貝到/usr/bin目錄下,這樣直接輸入rabbitmq-server命令就能夠了。啓動rabbitmq-server以後,咱們須要編寫客戶端的例子。因爲我使用的是erlang的例子,因此應該有erlang的運行環境。
git clone git://github.com/rebar/rebar.git cd rebar ./bootstrap
上面編譯好以後,在當前目錄下就會生成一個名爲"rebar"獨立的erlang腳本(escript),把它放在你想建立標準Erlang/OTP項目的目錄路徑下便可使用,或者把rebar放在/usr/bin目錄下,就像前面的rabbitmq-server同樣,能夠直接在shell裏面運行rebar命令。之因此推薦使用rebar,是由於rabar真的很好用,構建erlang的項目特別方便,還能自動生成gen_server等的代碼模板。我在使用了一次rebar以後,就決定之後全部的erlang項目都使用rebar來構建(說得好像本身能寫多少erlang項目似的( ⊙ o ⊙ )),因此建議沒用過rebar的讀者好好看一下前面的rebar的參考文章。最後推薦一款erlang的編輯器:IntelliJ IDEA,它是java語言開發的集成環境,IntelliJ在業界被公認爲最好的java開發工具之一,可是它對erlang的支持也很是完善,比我以前用來編寫erlang的sublime好用得多。讀者能夠去他的官網下載對應環境的版本,而後參考使用IntelliJ IDEA配置Erlang開發環境配置erlang環境。Intellij IDEA能夠選擇erlang環境,安裝rebar插件,還提供了shell能夠直接運行erl命令,十分方便。若是Intellij IDEA的中文輸入有問題,能夠參考這篇文章:完全解決了Intellij IDEA 2017.2 中文沒法輸入及中英文無法自由切換的問題。若是沒有安裝這個軟件也不要緊,下面的例子都會使用rebar命令來完成編譯。python
環境配置好了以後,咱們就能夠開始編寫hello world的例子了。我這邊的測試環境是在linux上面,rabbitmq的客戶端和服務端都在上面完成(windows下面用Intellij IDEA + rebar能夠搞定客戶端)。前面說過,直接運行 sbin/rabbitmq-server -detached 就將服務端啓動了。接下來的工做都是erlang客戶端的工做。linux
./rebar create-app appid=myapp
就能夠生成src文件夾,src文件夾中的myapp.app.src是OTP應用程序的資源文件,myapp_app.erl是OTP應用程序的Application behaviour,myapp_sup.erl是OTP應用程序的Supervisor behaviour。
git
-module(myapp_app). -behaviour(application). -include_lib("amqp_client/include/amqp_client.hrl"). %% Application callbacks -export([start/2, stop/1]). -export([test/0]). %% =================================================================== %% Application callbacks %% =================================================================== start(_StartType, _StartArgs) -> myapp_sup:start_link(). stop(_State) -> ok. test() -> %% Start a network connection {ok, Connection} = amqp_connection:start( #amqp_params_network{ host = "192.168.3.142", username = <<"test_user">>, password = <<"123456">>, virtual_host = <<"mytest">> }), io:format("connection"), %% Open a channel on the connection {ok, Channel} = amqp_connection:open_channel(Connection), %% Declare a queue #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), %% Publish a message Payload = <<"foobar">>, Publish = #'basic.publish'{exchange = <<>>, routing_key = Q}, amqp_channel:cast(Channel, Publish, #amqp_msg{payload = Payload}), %% Get the message back from the queue Get = #'basic.get'{queue = Q}, {#'basic.get_ok'{delivery_tag = Tag}, Content} = amqp_channel:call(Channel, Get), #amqp_msg{payload = Body} = Content, io:format("Body:~p~n",[Body]), %% Do something with the message payload %% (some work here) %% Ack the message amqp_channel:cast(Channel, #'basic.ack'{delivery_tag = Tag}), %% Close the channel amqp_channel:close(Channel), %% Close the connection amqp_connection:close(Connection), ok.
從代碼中能夠看見用到了amqp_client,因此咱們應該下載rabbitmq的針對erlang的客戶端依賴,下面會講到這個,這裏咱們關注一下amqp_connection:start()這個函數,它的參數是一個結構體,在結構體中的變量中,username,password,virtual_host都是binary格式的,這個要注意,我以前就是寫成字符串格式,沒有轉成二進制格式,老是報錯。另外,因爲代碼中的這些值都是我自定義的,因此首先要在rabbitmq-server上面建立這些用戶和vhost,也就是在個人linux虛擬機192.168.3.142(就是個人rabbitmq-server服務器)上面,執行以下命令:程序員
#新增一個vhost sbin/rabbitmqctl add_vhost mytest #新增一個user sbin/rabbitmqctl add_user test_user 123456 #爲用戶設置vhost上面的權限 sbin/rabbitmqctl set_permissions -p mytest test_user ".*" ".*" ".*"
unzip ./amqp_client-3.6.12.ez unzip ./rabbit_common-3.6.12.ez
解壓以後就能看見兩個目錄,這兩個目錄中均有ebin目錄,已是編譯好了的代碼,能夠直接利用。在代碼目錄下新建rebar.config文件,在其中加入以下代碼:github
{lib_dirs, ["libs"]}.
./rebar compile cd ebin/ erl -pa ../libs/amqp_client-3.6.12/ebin/ -pa ../libs/rabbit_common-3.6.12/ebin/
這裏必定要加上 -pa的選項,選項裏面指定了加載rabbitmq的客戶端的ebin目錄,不然跑不起來。我查了不少資料發現都沒人說這個,也許這對於erlang程序員來講是再正常不過的事情,不過對於我這種新手來講,着實是花了不少時間摸索的。
能夠看到效果,這個「test」的例子已經成功的跑起來了。若是是windows下面用Intellij IDEA + rebar,編譯以後,用erl命令運行shell的時候也須要加-pa選項,將依賴的ebin目錄加進去。
另外,還有一種辦法,那就是執行 ./rebar shell 命令也能夠達到 -pa 的效果(同事erlang老司機教的)。
objective-c
./rebar shell
寫到這裏,一個rabbitmq的erlang客戶端的例子已經寫完了。本文其實花了不少功夫在環境搭建上面,真正的代碼其實很短。若是不想搭建這麼多環境,想快速體驗一下rabbitmq的安裝和例子,能夠參考這篇文章:rabbitmq安裝和運行rabbitmq-tutorials裏的erlang例子。下一篇博客,將會講解rabbitmq的使用,而後介紹利用rebar生成gen_server的模板,生成一個服務,方便調用。知識和文筆有限,不妥之處,還望指出,謝謝。shell