【RabbitMQ】CentOS安装RabbitMQ,及简单的Java客户端连接

在CentOS安装

Erlang的安装

因Rabbit MQ使用Erlang,所以需要先安装Erlang,安装过程中可能会遇到种种问题,可参考CentOS 6.5安装Erlang/OTP 17.0
Erlang可在Erlang Solutions下载,我安装的是esl-erlang_19.0~centos~6_amd64.rpm,个人是通过yum安装的:yum install esl-erlang_19.0~centos~6_amd64.rpm

安装完测试是否成功:

[root@blog third_package]# erl
Erlang/OTP 19 [erts-8.0] [source-790c521] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V8.0  (abort with ^G)

RabbitMQ的安装

然后就可以安装MQ了。

[root@blog third_package]# rpm -ivh rabbitmq-server-3.6.5-1.noarch.rpm

我这里遇到一个异常情况,系统中安装了esl-erlang_19.0~centos~6_amd64.rpm,并通过erl测试成功,但RabbitMQ仍然关联不上,报一下错误:

error: Failed dependencies:
        erlang >= R16B-03 is needed by rabbitmq-server-3.6.5-1.noarch

我这里选择忽略依赖的安装:

[root@blog third_package]# rpm -ivh --nodeps rabbitmq-server-3.6.5-1.noarch.rpm
Preparing...                ########################################### [100%]
   1:rabbitmq-server        ########################################### [100%]

后续开启控制台后,在控制台页面看到RabbitMQ实际关联上了Erlang 19.0

启动与停止

启动:

[root@blog ~]# rabbitmq-server start &
[1] 2349
[root@blog ~]# 
              RabbitMQ 3.6.5. Copyright (C) 2007-2016 Pivotal Software, Inc.
  ##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
  ##  ##
  ##########  Logs: /var/log/rabbitmq/rabbit@blog.log
  ######  ##        /var/log/rabbitmq/rabbit@blog-sasl.log
  ##########
              Starting broker...
 completed with 0 plugins.

查看进程:

[root@blog ~]# ps -ef | grep rabbitmq
root      3955 32602  0 13:46 pts/1    00:00:00 /bin/sh /usr/sbin/rabbitmq-server start
root      3965  3955  0 13:46 pts/1    00:00:00 su rabbitmq -s /bin/sh -c /usr/lib/rabbitmq/bin/rabbitmq-server  'start'
rabbitmq  3966  3965  0 13:46 ?        00:00:00 /bin/sh -e /usr/lib/rabbitmq/bin/rabbitmq-server start
rabbitmq  4061     1  0 13:46 ?        00:00:00 /usr/lib/erlang/erts-8.0/bin/epmd -daemon
rabbitmq  4077  3966  6 13:46 ?        00:00:00 /usr/lib/erlang/erts-8.0/bin/beam -W w -A 64 -P 1048576 -t 5000000 -stbt db -K true -B i -- -root /usr/lib/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/ebin -noshell -noinput -s rabbit boot -sname rabbit@blog -boot start_sasl -kernel inet_default_connect_options [{nodelay,true}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit error_logger {file,"/var/log/rabbitmq/rabbit@blog.log"} -rabbit sasl_error_logger {file,"/var/log/rabbitmq/rabbit@blog-sasl.log"} -rabbit enabled_plugins_file "/etc/rabbitmq/enabled_plugins" -rabbit plugins_dir "/usr/lib/rabbitmq/lib/rabbitmq_server-3.6.5/plugins" -rabbit plugins_expand_dir "/var/lib/rabbitmq/mnesia/rabbit@blog-plugins-expand" -os_mon start_cpu_sup false -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/var/lib/rabbitmq/mnesia/rabbit@blog" -kernel inet_dist_listen_min 25672 -kernel inet_dist_listen_max 25672 start
rabbitmq  4166  4077  0 13:46 ?        00:00:00 erl_child_setup 65535
rabbitmq  4173  4166  0 13:46 ?        00:00:00 inet_gethost 4
rabbitmq  4174  4173  0 13:46 ?        00:00:00 inet_gethost 4
root      4180 32602  0 13:47 pts/1    00:00:00 grep rabbitmq

查看状态:

[root@blog ~]# rabbitmqctl status
Status of node rabbit@blog ...
[{pid,4077},
 {running_applications,[{rabbit,"RabbitMQ","3.6.5"},
                        {os_mon,"CPO  CXC 138 46","2.4.1"},
                        {rabbit_common,[],"3.6.5"},
                        {ranch,"Socket acceptor pool for TCP protocols.",
                               "1.2.1"},
                        {xmerl,"XML parser","1.3.11"},
                        {mnesia,"MNESIA  CXC 138 12","4.14"},
                        {sasl,"SASL  CXC 138 11","3.0"},
                        {stdlib,"ERTS  CXC 138 10","3.0"},
                        {kernel,"ERTS  CXC 138 10","5.0"}]},
 {os,{unix,linux}},
 {erlang_version,"Erlang/OTP 19 [erts-8.0] [source-790c521] [64-bit] [async-threads:64] [hipe] [kernel-poll:true]\n"},
 {memory,[{total,43961024},
          {connection_readers,0},
          {connection_writers,0},
          {connection_channels,0},
          {connection_other,0},
          {queue_procs,2688},
          {queue_slave_procs,0},
          {plugins,0},
          {other_proc,18589480},
          {mnesia,57432},
          {mgmt_db,0},
          {msg_index,38392},
          {other_ets,926384},
          {binary,19600},
          {code,17725357},
          {atom,752561},
          {other_system,5849130}]},
 {alarms,[]},
 {listeners,[{clustering,25672,"::"},{amqp,5672,"0.0.0.0"}]},
 {vm_memory_high_watermark,0.4},
 {vm_memory_limit,787311820},
 {disk_free_limit,50000000},
 {disk_free,36167917568},
 {file_descriptors,[{total_limit,65435},
                    {total_used,2},
                    {sockets_limit,58889},
                    {sockets_used,0}]},
 {processes,[{limit,1048576},{used,137}]},
 {run_queue,0},
 {uptime,58},
 {kernel,{net_ticktime,60}}]

停止:

[root@blog ~]# rabbitmqctl stop
Stopping and halting node rabbit@blog ...
Gracefully halting Erlang VM

Java客户端连接

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>4.0.0</version>
</dependency>
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class Producer {

    private final static String QUEUE_NAME = "hello world";

    public static void main(String[] argv) throws Exception {
        
        Connection connection = null;
        Channel channel = null;
        try {
            /* 创建连接工厂 */
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("192.168.1.101");
            factory.setPort(5672);
            factory.setUsername("nicchagil");
            factory.setPassword("123456");
            /* 创建连接 */
            connection = factory.newConnection();
            /* 创建信道 */
            channel = connection.createChannel();

            // 声明一个队列:名称、持久性的(重启仍存在此队列)、非私有的、非自动删除的
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            
            String message = "hello world..."; // 需发送的信息
            
            /* 发送消息,使用默认的direct交换器 */
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println("Send message -> " + message);
            
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            /* 关闭连接、通道 */
            channel.close();
            connection.close();
            System.out.println("Closed the channel and conn.");
        }

    }

}
import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class Customer {

    private final static String QUEUE_NAME = "hello world";

    public static void main(String[] argv) throws java.io.IOException,
            java.lang.InterruptedException, TimeoutException {

        /* 创建连接工厂 */
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.1.101");
        factory.setPort(5672);
        factory.setUsername("nicchagil");
        factory.setPassword("123456");
        /* 创建连接 */
        Connection connection = factory.newConnection();
        /* 创建信道 */
        Channel channel = connection.createChannel();

        // 声明一个队列:名称、持久性的(重启仍存在此队列)、非私有的、非自动删除的
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        System.out.println("Waiting for messages.");

        /* 定义消费者 */
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                    AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("Received the message -> " + message);
            }
        };
        
        // 将消费者绑定到队列,并设置自动确认消息(即无需显示确认,如何设置请慎重考虑)
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}

消息持久化

为了避免RabbitMQ重启或宕机导致消息丢失,我们需要设置消息持久性。

而设置消息持久性,主要分两步:

  • 设置队列是持久的
  • 发送消息时,设置消息是持久的

设置队列是持久的:

// 声明一个队列:名称、持久性的(重启仍存在此队列)、非私有的、非自动删除的
channel.queueDeclare(QUEUE_NAME, true, false, false, null);

发送消息时,设置消息是持久的:

channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

RabbitMQ、Erlang之间的版本关系说明

安装RabbitMQ之前,要安装Erlang,而Erlang与RabbitMQ之间是有版本关系的,见 Erlang Versions Required and Supported by RabbitMQ
所以,安装rabbitmq-server-3.5.7,使用yum install rabbitmq-server-3.5.7-1.noarch.rpm即可。

RabbitMQ的集群

RabbitMQ配置集群的文章可见Clustering Guide。这里只简单介绍一下,因环境受限,只部署两个实例组成集群。

这种集群方式,默认同步节点的元数据,比如队列元数据交换器元数据绑定元数据vhost元数据,但默认不同步队列的内容

  • 现以单节点方式启动各节点:rabbitmq-server -detached
  • 启动后可查看集群状态:rabbitmqctl cluster_status,不出意外,这里只能看到单一节点的集群
  • 现关闭节点2的应用,以准备加入节点1的集群:rabbitmqctl stop_app
  • 加入节点1的集群:rabbitmqctl join_cluster rabbit@节点机器,当然节点2可能并不认识节点1,可在/etc/hosts加入IP与HOST的映射
  • 启动节点2的应用:rabbitmqctl start_app,如无意外,2个节点已形成集群,你在任意节点操作元数据,在另外的节点可体现
  • 可再次查看确认集群状态:rabbitmqctl cluster_status

可以用rabbitmqctl stop_apprabbitmqctl stop模拟节点故障而宕掉,当故障节点重新启动后可见故障期间改动的元数据体现在重新启动的故障节点上。

插件与Web控制台

[root@blog ~]# rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
  mochiweb
  webmachine
  rabbitmq_web_dispatch
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management

Applying plugin configuration to rabbit@ebadb-pdwy... started 6 plugins.

开启后,可以在http://xx.xx.xx.xx:15672访问控制台。如果你在其他机器访问控制台,有可能出现访问不了的情况,试试将Linus防火墙设置一下。

以前的版本通过账号/密码:guest/guest就可以登录访问,安装新版本后就不行了,所以自己新建用户,并授予角色和权限,具体可参考这篇文章:rabbitmq的web管理界面无法使用guest用户登录

rabbitmqctl add_user nicchagil 123456 # 常见用户
rabbitmqctl set_user_tags nicchagil administrator # 授予administrator角色给nicchagil
rabbitmqctl set_permissions -p / nicchagil '.*' '.*' '.*' # 授予权限

可查看当前插件:

[root@blog ~]# rabbitmq-plugins list
 Configured: E = explicitly enabled; e = implicitly enabled
 | Status:   * = running on rabbit@blog
 |/
[e*] amqp_client                       3.6.5
[  ] cowboy                            1.0.3
[  ] cowlib                            1.0.1
[e*] mochiweb                          2.13.1
[  ] rabbitmq_amqp1_0                  3.6.5
[  ] rabbitmq_auth_backend_ldap        3.6.5
[  ] rabbitmq_auth_mechanism_ssl       3.6.5
[  ] rabbitmq_consistent_hash_exchange 3.6.5
[  ] rabbitmq_event_exchange           3.6.5
[  ] rabbitmq_federation               3.6.5
[  ] rabbitmq_federation_management    3.6.5
[  ] rabbitmq_jms_topic_exchange       3.6.5
[E*] rabbitmq_management               3.6.5
[e*] rabbitmq_management_agent         3.6.5
[  ] rabbitmq_management_visualiser    3.6.5
[  ] rabbitmq_mqtt                     3.6.5
[  ] rabbitmq_recent_history_exchange  1.2.1
[  ] rabbitmq_sharding                 0.1.0
[  ] rabbitmq_shovel                   3.6.5
[  ] rabbitmq_shovel_management        3.6.5
[  ] rabbitmq_stomp                    3.6.5
[  ] rabbitmq_top                      3.6.5
[  ] rabbitmq_tracing                  3.6.5
[  ] rabbitmq_trust_store              3.6.5
[e*] rabbitmq_web_dispatch             3.6.5
[  ] rabbitmq_web_stomp                3.6.5
[  ] rabbitmq_web_stomp_examples       3.6.5
[  ] sockjs                            0.3.4
[e*] webmachine                        1.10.3

当然也可禁用插件:

[root@blog ~]# rabbitmq-plugins disable rabbitmq_management
The following plugins have been disabled:
  mochiweb
  webmachine
  rabbitmq_web_dispatch
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management

Applying plugin configuration to rabbit@blog... stopped 6 plugins.

消息跟踪,Message Tracing

在开发和测试阶段,有时候需跟踪消息的生产与消费,我们可开启Message Tracing
开启Message Tracing插件:rabbitmq-plugins enable rabbitmq_tracing,然后Web控制台的Admin -> Tracing可进入消息跟踪页面,在此页面可以新增一个trace,然后通过命令rabbitmqctl trace_on开启消息跟踪,如果有消息的生产和消费,就会记录在一个日志文件中。
需注意,RabbitMQ重启后,你新建的trace会消失。
更多说明见Firehose Tracer

修改MQ默认配置

生成并编辑/etc/rabbitmq/rabbitmq.config即可:

mkdir -p /etc/rabbitmq
cp /usr/share/doc/rabbitmq-server-3.6.11/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config

修改MQ监听端口

编辑tcp_listeners块,具体配置见Networking and RabbitMQ

   {tcp_listeners, [{"xx.xx.xx.xx", xxxx}]}

修改Web控制台端口

编辑rabbitmq_management块:

 {rabbitmq_management,
  [
   {listener, [{port,     xxxx},
               {ip,       "xx.xx.xx.xx"},
               {ssl,      false}]}
  ]},

参考的文章

posted @ 2016-12-12 22:23  nick_huang  阅读(2133)  评论(0编辑  收藏  举报