RabbitMQ基础入门(一)

RabbitMQ是一款优秀的消息队列中间件,它广泛应用于企业级应用中,可以帮助应用解耦,面对一些业务场景起到一个很强的分流作用等等。为什么挑选RabbitMQ进行学习呢,主要是因为它支持大多数协议,支持AMQP协议,而且官方文档相当全面,今天面向官方文档进行一个基础入门。题主使用的语言是JAVA。

RabbitMQ是基于Erlang语言进行编写的,所以如果想要使用RabbitMQ,首先需要安装Erlang语言的环境。

关于Erlang语言的安装百度有很多也很简单,RabbitMQ也是很容易安装,同时提供了简单的CTL工具供操作。

CTL的官方文档:http://www.rabbitmq.com/man/rabbitmqctl.8.html

今天入门的主题是如何进行消息的发布和消费,在Java中分为几个步骤,其它语言也类似

1.建立连接工厂,生成实例

2.配置host,账号密码等

3.从工厂实例生成Connection连接

4.利用Connection生成信道Channel(RabbitMQ提供信道供客户端与MQ SERVER进行通信,此处是长连接,因为TCP短连接建立销毁的开销太大了)

5.声明队列或者交换器

(第五点根据个人实验,如果是直接声明队列的话,是会生成一条具体队列的,而且会默认选择一个exchange,但是如果声明交换器的话,无需声明队列,RabbitMQ会自动建立队列,而且一个消费者客户端对应的一个queue)

6.开始执行工作(生产者发布消息,消费者消费消息)

关于声明交换器的代码我就不写了,因为在我转载的上一篇来自简书的文章里已经写得很清楚了,这里根据官方文档写一个简单的声明队列的例子

首先需要在Maven环境下引入依赖

   
      com.rabbitmq
      amqp-client
      4.1.0
   

生产者例子:

package com.wuweixin;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

public class rabbitmq_persistent_publisher {

    public static String persistent_queue = "persistent_queue";


    public static void main(String[] args) throws Exception{

        ConnectionFactory connectionFactory =  new ConnectionFactory();
        connectionFactory.setHost("localhost");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        boolean isPersist = true;
        channel.queueDeclare(persistent_queue,isPersist,false,false,null);
        int index = 1;
        while(index++<1000){
            String message = "这是第 "+index+" 条信息";
            channel.basicPublish("",persistent_queue, MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes("utf-8"));
            System.out.println(message);
        }
        channel.close();
        connection.close();
    }

}

消费者例子:

package com.wuweixin;

import com.rabbitmq.client.*;

import java.io.IOException;

public class rabbitmq_persistent_consumer {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory =  new ConnectionFactory();
        connectionFactory.setHost("localhost");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        Connection connection = connectionFactory.newConnection();
        final Channel channel = connection.createChannel();
        channel.basicQos(1);//告诉MQ SERVER如果未发送确认后,不要继续发送消息给我
        channel.queueDeclare(rabbitmq_persistent_publisher.persistent_queue,true,false,false,null);
        boolean autoAck = false;//关闭确认消息,由我们自己来控制
        final Consumer consumer =  new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String messsage = new String(body,"utf-8");
                System.out.println("收到:"+messsage);
                try{
                    Thread.sleep(2000);
                }catch (Exception e){
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(rabbitmq_persistent_publisher.persistent_queue,autoAck,consumer);
    }
}

这样运行起来就可以不断地向队列发布和消费消息了。

这里面有几个点值得注意,就是关于队列持久化和确认问答的要点

1.在生产者端,在声明队列的时候,第二个参数是定义该队列是否是可持久化的,如果选择true的话,那么在发布消息的时候,需要传入的消息属性也必须为可持久化的配置,这两步中,消费者也是一样的配置

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.rabbitmq.client;

import com.rabbitmq.client.AMQP.BasicProperties;
import java.util.Date;
import java.util.Map;

public class MessageProperties {
    public static final BasicProperties MINIMAL_BASIC = new BasicProperties((String)null, (String)null, (Map)null, (Integer)null, (Integer)null, (String)null, (String)null, (String)null, (String)null, (Date)null, (String)null, (String)null, (String)null, (String)null);
    public static final BasicProperties MINIMAL_PERSISTENT_BASIC = new BasicProperties((String)null, (String)null, (Map)null, Integer.valueOf(2), (Integer)null, (String)null, (String)null, (String)null, (String)null, (Date)null, (String)null, (String)null, (String)null, (String)null);
    public static final BasicProperties BASIC = new BasicProperties("application/octet-stream", (String)null, (Map)null, Integer.valueOf(1), Integer.valueOf(0), (String)null, (String)null, (String)null, (String)null, (Date)null, (String)null, (String)null, (String)null, (String)null);
    public static final BasicProperties PERSISTENT_BASIC = new BasicProperties("application/octet-stream", (String)null, (Map)null, Integer.valueOf(2), Integer.valueOf(0), (String)null, (String)null, (String)null, (String)null, (Date)null, (String)null, (String)null, (String)null, (String)null);
    public static final BasicProperties TEXT_PLAIN = new BasicProperties("text/plain", (String)null, (Map)null, Integer.valueOf(1), Integer.valueOf(0), (String)null, (String)null, (String)null, (String)null, (Date)null, (String)null, (String)null, (String)null, (String)null);
    public static final BasicProperties PERSISTENT_TEXT_PLAIN = new BasicProperties("text/plain", (String)null, (Map)null, Integer.valueOf(2), Integer.valueOf(0), (String)null, (String)null, (String)null, (String)null, (Date)null, (String)null, (String)null, (String)null, (String)null);

    public MessageProperties() {
    }
}

2.关于确认消息

RabbitMQ有一个确认的机制,消费者必须确认消息返回后,MQ SERVER才默认这条消息已经被消费,否则这条消息会被重复消费,同样也是配置一个参数,默认是自动确认的,但最好是我们在编写业务逻辑的时候自己手动确认。

3.还有消费者是否接受消息的一个配置

channel.basicQos(int)

该配置可以设置如果消费者还没返回上一条消息的确认时,是否还接受消息,接受多少条,这样就可以避免RabbitMQ循环发送的平均分配机制可能会压死单一节点

 

今天的分享就到这里了,谢谢浏览!

你可能感兴趣的:(消息队列)