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