rabbitMQ 初探-环境搭建、erlang客户端例子教程

二次信任 提交于 2019-11-29 02:39:11

rabbitMQ 初探-环境搭建、erlang客户端例子教程


1. rabbitMQ简介

    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代码,都曲折无比,不能正常跑起来。所以将遇到的一些坑记录下来,希望能减少后来者的时间。)

    rabbitmq是一个订阅-发布的消息队列,生产者生成数据,发往rabbitmq,消费者根据订阅,消费生产者的消息。


2. 环境搭建

    我的rabbitmq是安装在linux环境下的,erlang客户端可以跑在linux下,也可以跑在windows下。

  •  第一步是下载安装rabbitmq,去官网的下载页面选择适合自己的版本,我选择的是rabbitmq-server-generic-unix-3.6.12.tar.xz,然后解压,
    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的运行环境。
  • 第二步是客户端的环境,包括安装erlang环境,并且安装rebar。安装erlang环境并不在本文的讲解之列,读者可以参考这篇文章自行安装:源码安装erlang。rebar的安装可以参考这篇文章:用 rebar 来构建、编译、测试、发布 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命令来完成编译。

3. hello world例子

    环境配置好了之后,我们就可以开始编写hello world的例子了。我这边的测试环境是在linux上面,rabbitmq的客户端和服务端都在上面完成(windows下面用Intellij IDEA + rebar可以搞定客户端)。前面说过,直接运行 sbin/rabbitmq-server -detached 就将服务端启动了。接下来的工作都是erlang客户端的工作。

  • 首先新建一个“my_rabbit_test”文件夹,将前面生成的可执行文件rebar拷贝进去。
  • 我们利用rebar构建项目的骨架,执行命令:
    ./rebar create-app appid=myapp

    就可以生成src文件夹,src文件夹中的myapp.app.src是OTP应用程序的资源文件,myapp_app.erl是OTP应用程序的Application behaviour,myapp_sup.erl是OTP应用程序的Supervisor behaviour。

  • 接下来继续执行 ./rebar compile,能够看见生成了ebin目录,ebin中的myapp.app文件指定了起始模块是myapp_app。src目录中的“myapp.app.src”同样指定了这些。如果我们进入到 ebin目录,然后执行erl进入erl的shell界面的话,输入 application:start(myapp)就能启动 myapp_app 模块了。 所以我们要做的就是往 myapp_sup.erl和myapp_app.erl塞代码。
  • 我们在myapp_app.erl中加入一段简单的测试代码
  • -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 ".*" ".*" ".*"

  • 由于代码中依赖了rabbitmq的客户端,所以我们需要下载这个依赖。我们首先在代码目录下新建一个libs目录,然后将需要下载的两个依赖amqp_clientrabbit_common下载到该目录下,然后解压
  • unzip ./amqp_client-3.6.12.ez 
    unzip ./rabbit_common-3.6.12.ez

    解压之后就能看见两个目录,这两个目录中均有ebin目录,已经是编译好了的代码,可以直接利用。在代码目录下新建rebar.config文件,在其中加入如下代码:

  • {lib_dirs, ["libs"]}.
  • 然后我们就可以在代码目录下执行 ./rebar compile命令进行编译了,编译之后的beam文件在ebin目录下,进入ebin目录,执行erl -pa 的命令开始测试
  • ./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老司机教的)。
     

    ./rebar shell

    写到这里,一个rabbitmq的erlang客户端的例子已经写完了。本文其实花了很多功夫在环境搭建上面,真正的代码其实很短。如果不想搭建这么多环境,想快速体验一下rabbitmq的安装和例子,可以参考这篇文章:rabbitmq安装和运行rabbitmq-tutorials里的erlang例子。下一篇博客,将会讲解rabbitmq的使用,然后介绍利用rebar生成gen_server的模板,生成一个服务,方便调用。知识和文笔有限,不妥之处,还望指出,谢谢。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!