消息中间件rabbitMQ入门(一):简单介绍和使用

一、安装

1、erlang 安装

安装Erlang OTP,由于RabbitMQ是用Erlang编写的,所以在安装RabbitMQ之前要先安装Erlang 下载地址:http://www.erlang.org/downloads 下载最新版本即可,例如下载解压后运行 otp_win64_18.1.exe, 然后一直默认下一步下一步即可,没有什么特别说明的。使用默认设置安装完毕之后,会在看到 erl.exe 文件,它就相当于 jdk里的 java.exe。 这就说明安装好了。
安装完成后我们就要来配置环境变量了:
找到【我的电脑】右键【属性】–》【高级系统设置】–》选择【高级】–》【环境变量】–》【新建】
1、在系统变量中新建变量:ERLANG_HOME,变量值为安装Erlang的路径(不经不要包含bin目录)
在这里插入图片描述2、新建一个系统变量:变量名为ERLANG_HOME,变量值为安装Erlang的路径(路径中不要包含bin目录)
3、将新建的系统变量添加在【系统变量】Path中:格式为%ERLANG_HOME%\bin(这里我用的win7添加path的)
在这里插入图片描述
4、然后我们打开cmd输入erl查看是Erlan是否安装好、下图就表示已经安装好了
在这里插入图片描述

2、安装RabbitMQ

安装RabbitMQ,在官网上下载最新的RabbitMQ(http://www.rabbitmq.com/)
步骤1:例如下载安装运行里面的 rabbitmq-server-3.6.5.exe ,使用默认设置,下一步下一步即可。安装成功之后,在如图所示位置可以看到这些文件就表示安装OK了。
在这里插入图片描述
步骤2、

  1. 首先使用cmd进入sbin目录(我的sbin目录是:D:\javadevelop\rabbitMq\RabbitMQ Server\rabbitmq_server-3.6.5\sbin)
  2. 然后输入: rabbitmq-plugins.bat enable rabbitmq_management 开启插件
    在这里插入图片描述
  3. 重启 rabbitmq,运行命令: net stop RabbitMQ && net start RabbitMQ
    (如下图表示重启成功)
    在这里插入图片描述
  4. 访问管理界面输入网址:http://127.0.0.1:15672, 账号:guest,密码:guest
  5. 管理界面登录成功
    在这里插入图片描述

二、介绍

1、RABBITMQ - 模式讲解

步骤1:AMQP
与activemq不一样, rabbitmq 使用的是一种叫做 AMQP 的协议来通信。 AMQP 是 dvanced Message Queuing Protocol 的缩写。协议内容我们就没必要深入研究了,简单地说,通过这种协议,可以处理更为复杂的业务需求~以下就是基于 AMQP 这种协议,可以实现的各种模式

步骤 2 : 消息路由过程
与 ActiveMQ 拿到消息就直接放在队列等待消费者拿走不同, Rabbit 拿到消息之后,会先交给 交换机 (Exchange), 然后交换机再根据预先设定的不同绑定( Bindings )策略,来确定要发给哪个队列。如图所示,比起 ActiveMQ 多了 Exchange 和 Bindings。正式由于有了 Exchange 和 Bindings, RabbitMQ 就可以灵活地支撑各种模式。
在这里插入图片描述

步骤 3 : 模式
RabbitMQ提供了四种Exchange模式:fanout,direct,topic,header 。 header模式在实际使用中较少,这里只讨论前三种模式.

1、fanout 模式:fanout 模式就是广播模式,消息来了会发给所有的队列
在这里插入图片描述
2、Direct 模式:Direct 模式就是指定队列模式, 消息来了,只发给指定的 Queue, 其他Queue 都收不到。
在这里插入图片描述
3、Topic 模式:主题模式,注意这里的主题模式,和 ActivityMQ 里的不一样。 ActivityMQ 里的主题,更像是广播模式。

那么这里的主题模式是什么意思呢? 如图所示消息来源有: 美国新闻,美国天气,欧洲新闻,欧洲天气。
如果你想看 美国主题: 那么就会收到 美国新闻,美国天气。
如果你想看 新闻主题: 那么就会收到 美国新闻,欧洲新闻。
如果你想看 天气主题: 那么就会收到 美国天气,欧洲天气。
如果你想看 欧洲主题: 那么就会收到 欧洲新闻,欧洲天气。
这样就可以灵活搭配~
在这里插入图片描述

2、RABBITMQ - 模式代码

2.1 FANOUT 模式代码

发送消息

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

//生产者
public class TestProducer {

    //定义交换模式名称
    private static  final  String EXCHANGE_NAME="fanout_exchange";
    
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {

        //检查服务是否启动
        RabbitMQUtil.checkServer();

        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置RabbitMQ相关信息
        connectionFactory.setHost("localhost");
        //创建一个新的连接
        Connection connection = connectionFactory.newConnection();
        ///创建一个通道
        Channel channel = connection.createChannel();
        //交换模式声明
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");

        //消息发送代码
        for(int i=0;i<100;i++){

            Thread.sleep(1000);
            //生产者发送消息
            String message="fanout模式下消息发送  "+i;
            byte[] bytes = message.getBytes("UTF-8");
            channel.basicPublish(EXCHANGE_NAME,"",null,bytes);
            System.out.println("发送消息: " + message);
        }

        //关闭
        channel.close();
        connection.close();
    }

}

在这里插入图片描述

接收消息:

package com.example.rabbitmq;
import cn.hutool.core.util.RandomUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;


//消费者
public class TestDriectCustomer {


    private static final String EXCHANGE_NAME="fanout_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {

        //检查服务是否启动
        RabbitMQUtil.checkServer();
        //为当前消费者取随机名
        String name="consumer-"+RandomUtil.randomString(5);

        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //这里设置RabbitMq连接设置
        connectionFactory.setHost("localhost");
        //新建连接
        Connection connection = connectionFactory.newConnection();
        //创建渠道
        Channel channel = connection.createChannel();
        //交换机声明(交换名称,交换模式)
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");


        //获取消息队列名称
        String queue = channel.queueDeclare().getQueue();
        //队列与交换机绑定(参数为:队列名称;交换机名称;routingKey忽略)
        channel.queueBind(queue,EXCHANGE_NAME, "");

        //等待消息
        System.out.println(name+" 等待消息......");
         //DefaultConsumer类实现了Consumer接口,通过传入一个频道,
        // 告诉服务器我们需要那个频道的消息,如果频道中有消息,就会执行回调函数handleDelivery
        DefaultConsumer 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(name+" "+"接收到来自消息: "+message);


            }
        };

        //自动回复队列应答 -- RabbitMQ中的消息确认机制
        channel.basicConsume(queue,true,consumer);

    }
    

}

先运行两次 TestCustomer,启动两个消费者。然后运行一次 TestProducer, 启动生产者,生产100条信息。 此时就可以看到如图所示两个消费者都能收到 这100条信息。
在这里插入图片描述
pom.xml中:提供 rabbitmq和hutool的jar

    <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>3.6.5</version>
     </dependency>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>4.3.1</version>
    </dependency>

2.2 DIRECT 模式代码

发送消息

package com.example.rabbitmq;

import cn.hutool.core.util.NetUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;


//exchange的driect模式
public class TestDriectProducer {

    public final static String QUEUE_NAME="direct_queue";
    public static void main(String[] args) throws IOException, TimeoutException, TimeoutException, InterruptedException {

        //检验服务器是否
        if(NetUtil.isUsableLocalPort(15672)) {
            System.out.println("RabbitMQ 服务器未启动 ");
            System.exit(1);
        }

        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置RabbitMQ相关信息
        factory.setHost("localhost");
        //创建一个新的连接
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();
        //交换模式声明
        channel.exchangeDeclare(QUEUE_NAME,"direct");
        for (int i = 0; i < 100; i++) {
            Thread.sleep(1000);
            String message = "direct 消息 " +i;
            //发送消息到队列中
            //参数说明:string exchange -- 交换机名称,String routingKey -- 路由关键字,BasicProperties props -- 消息的基本属性,例如路由头等,
            //byte[] body -- 消息体
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
            System.out.println("发送消息: " + message);

        }
        //关闭通道和连接
        channel.close();
        connection.close();
    }

}

接收消息

package com.example.rabbitmq;

import cn.hutool.core.util.NetUtil;
import cn.hutool.core.util.RandomUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;


//消息消费者:direct模式下
public class TestDirectCustomer {

    private final static String QUEUE_NAME = "direct_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        //检验服务器是否
        if(NetUtil.isUsableLocalPort(15672)) {
            System.out.println("RabbitMQ 服务器未启动 ");
            System.exit(1);
        }

        //为当前消费者取随机名
        String name = "consumer-"+ RandomUtil.randomString(5);
        //判断服务器是否启动
        RabbitMQUtil.checkServer();
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置RabbitMQ地址
        factory.setHost("localhost");
        //创建一个新的连接
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();
        //交换模式声明
        channel.exchangeDeclare(QUEUE_NAME,"direct");

        //声明要关注的队列,参数:队列名称;是否持久化;是否排外的;是否自动删除
        channel.queueDeclare(QUEUE_NAME, false, false, true, null);
        System.out.println(name +" 等待接受消息");
        //DefaultConsumer类实现了Consumer接口,通过传入一个频道,
        // 告诉服务器我们需要那个频道的消息,如果频道中有消息,就会执行回调函数handleDelivery
        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(name + " 接收到消息 '" + message + "'");
            }
        };

        //自动回复队列应答 -- RabbitMQ中的消息确认机制
        //参数:队列名称;消息标记;消费者
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }

}

运行一次生产者TestDriectProducer,两次消费者TestDirectCustomer
在这里插入图片描述

2.2 TOPIC 模式代码

发送消息

package com.example.rabbitmq;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;


//消息生成者
public class TestTopicProducer {

    public final static String EXCHANGE_NAME="topics_exchange";
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
    
        //检验服务器是否
        if(NetUtil.isUsableLocalPort(15672)) {
            System.out.println("RabbitMQ 服务器未启动 ");
            System.exit(1);
        }
        
        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置RabbitMQ相关信息
        factory.setHost("localhost");
        //创建一个新的连接
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");

        String[] routing_keys = new String[] { "usa.news", "usa.weather",
                "europe.news", "europe.weather" };
        String[] messages = new String[] { "美国新闻", "美国天气",
                "欧洲新闻", "欧洲天气" };

        for (int i = 0; i < routing_keys.length; i++) {
            Thread.sleep(5000);
            String routingKey = routing_keys[i];
            String message = messages[i];
            channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
            System.out.printf("发送消息到路由:%s, 内容是: %s%n ", routingKey,message);

        }

        //关闭通道和连接
        channel.close();
        connection.close();
    }


}



接收消息:专门用于接受 usa.* 消息

package com.example.rabbitmq;

import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;


//设置路由,专门用于接受 usa.* 消息
public class TestTopicCustomer1 {

    public final static String EXCHANGE_NAME="topics_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        //检验服务器是否
        if(NetUtil.isUsableLocalPort(15672)) {
            System.out.println("RabbitMQ 服务器未启动 ");
            System.exit(1);
        }
        
        //为当前消费者取名称
        String consumerName = "consumer-usa";
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置RabbitMQ地址
        factory.setHost("localhost");
        //创建一个新的连接
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();

        //交换机声明(参数为:交换机名称;交换机类型)
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");
        //获取一个临时队列
        String queue = channel.queueDeclare().getQueue();

        //接受USA信息
        //参数:String queue, String exchange, String routingKey
        channel.queueBind(queue, EXCHANGE_NAME, "usa.*");
        System.out.println(consumerName +" 等待接受消息");
        //DefaultConsumer类实现了Consumer接口,通过传入一个频道,
        // 告诉服务器我们需要那个频道的消息,如果频道中有消息,就会执行回调函数handleDelivery
        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(consumerName + " 接收到消息 '" + message + "'");
            }
        };

        //自动回复队列应答 -- RabbitMQ中的消息确认机制
        channel.basicConsume(queue, true, consumer);
    }


}


接收消息:专门用于接受 *.news 消息

package com.example.rabbitmq;

import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;



public class TestTopicCustomer2 {

    public final static String EXCHANGE_NAME="topics_exchange";

    //设置路由,专门用于接受 *.news  消息
    public static void main(String[] args) throws IOException, TimeoutException {

        //为当前消费者取名称
        String consumerName = "consumer-news";
        //判断服务器是否启动
        RabbitMQUtil.checkServer();
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置RabbitMQ地址
        factory.setHost("localhost");
        //创建一个新的连接
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();
        //交换机声明(参数为:交换机名称;交换机类型)
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");
        //获取一个临时队列
        String queueName = channel.queueDeclare().getQueue();
        //接受 USA 信息
        //String queue, String exchange, String routingKey
        channel.queueBind(queueName, EXCHANGE_NAME, "*.news");
        System.out.println(consumerName +" 等待接受消息");
        //DefaultConsumer类实现了Consumer接口,通过传入一个频道,
        // 告诉服务器我们需要那个频道的消息,如果频道中有消息,就会执行回调函数handleDelivery
        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(consumerName + " 接收到消息 '" + message + "'");
            }
        };
        //自动回复队列应答 -- RabbitMQ中的消息确认机制
        channel.basicConsume(queueName, true, consumer);

    }

}

运行一次生产者TestTopicProducer,两次消费者TestTopicCustomer1,TestTopicCustomer2,运行结果如下图
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值