一,RabbitMQ的简单了解

RabbitMQ是目前非常热门的一款消息中间件,经常使用于并发量比较高的场景。用电商下单过程作为一个简单列子,按照传统的方式,下单过程要等到调用完毕之后才能返回下单成功,如果网络产生波动等原因使得商品服务扣库存延迟或者失败,这样就会导致较差的用户体验。
消息队列提供一个异步通信机制,消息的发送者不必一直等待到消息被成功处理才返回,而是立即返回。消息中间件负责处理网络通信,如果网络连接不可用,消息被暂存于队列当中,当网络畅通的时候在将消息转发给相应的应用程序或者服务,当然前提是这些服务订阅了该队列。

二,RabbitMQ简单队列

消息队列rabbitmq详解 消息队列rabbitmq例子_rabbitmq

接下来我们用代码简单模拟 消息生产者P 发送一条信息到红色队列中,然后消费者C从队列中获取到消息首先我们要在RabbitMQ上建立一个virtual host

消息队列rabbitmq详解 消息队列rabbitmq例子_消息队列rabbitmq详解_02

建立一个maven项目,对应的pom文件引入的依赖

<!-- 引入队列依赖 -->
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>4.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.10</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

对应的Java代码:

简单的包结构

消息队列rabbitmq详解 消息队列rabbitmq例子_rabbitmq_03


这是util包下的ConnectionUtils

package com.liao.rabbitmq.util;

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

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

public class ConnectionUtils {

    /**
     * 获取MQ链接
     */
    public static Connection getConnection() throws IOException, TimeoutException {

        //定义一个链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置服务器地址
        factory.setHost("127.0.0.1");
        //设置AMQP端口号
        factory.setPort(5672);
        //设置vhost
        factory.setVirtualHost("/vhost_mmr");
        //用户名
        factory.setUsername(" ");//自己登录RabbitMQ的用户名和密码
        //密码
        factory.setPassword(" ");//
        return factory.newConnection();
    }
}

消息生产者P
对应simple包下的Send类

package com.liao.rabbitmq.simple;

import com.liao.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

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

/**
 * 生产者,发送消息
 */
public class Send {

    private static final String QUEUE_NAME = "test_simple_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        //获取MQ链接
        Connection connection = ConnectionUtils.getConnection();
        //从链接中获取一个通道
        Channel channel = connection.createChannel();
        //创建队列声明
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //要发送的信息
        String msg = "hello simple queue";
        //进行发送
        channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
        System.out.println("发送信息:"+msg);
        //关闭链接
        channel.close();
        connection.close();

    }
}

消费者C
对应simple包下的Receive类

package com.liao.rabbitmq.simple;

import com.liao.rabbitmq.util.ConnectionUtils;
import com.rabbitmq.client.*;

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

/**
 * 消费者接受消息
 */
public class Receive {

    private static final String QUEUE_NAME = "test_simple_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取MQ链接
        Connection connection = ConnectionUtils.getConnection();
        //从链接中获取一个通道
        Channel channel = connection.createChannel();
        //创建队列声明
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //从消息队列中获取消息
        DefaultConsumer consumer = new DefaultConsumer(channel){
            //当消息队列中有消息时则会触发该方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {
                super.handleDelivery(consumerTag, envelope, properties, body);
                String msg  = new String(body,"utf-8");
                System.out.println("消费者接受到的消息: " + msg);
            }
        };
        //监听队列
        channel.basicConsume(QUEUE_NAME,true,consumer);
    }
}

运行效果:

消息队列rabbitmq详解 消息队列rabbitmq例子_java_04

运行send时,当该消息被接受后,这里的1则就没了

消息队列rabbitmq详解 消息队列rabbitmq例子_消息队列_05


消息队列rabbitmq详解 消息队列rabbitmq例子_消息队列rabbitmq详解_06

三,简单队列存在的问题

生产者与消费者属于一一对应的问题,如果存在多个消费时则不行。而且在实际开发中,一般生产者发送消息的速度是比较快的,而消费者则需要和业务结合,所以一般速度是比较慢的,所以这时则就会出现积压很多队列消息,这时就需要工作队列来实现。