【RabbitMQ】入门

  •  RabbitMQ介绍

如下文章参考第一段

安装rabbitmq 设置用户_104、SpringBoot整合RabbitMQ_weixin_39765100的博客-CSDN博客

超详细的RabbitMQ入门_Rok728的博客-CSDN博客_rabbitmq教程

  • 安装

RabbitMQ基于Erlang语言编写,需要安装Erlang
Erlang 下载地址:https://www.erlang.org/downloads
安装:一键傻瓜式安装,安装完毕需要重启,需要依赖Windows组件
环境变量配置
ERLANG_HOME
PATH
 

RabbitMQ

下载地址:https://rabbitmq.com/install-windows.html
安装:一键傻瓜式安装
 

启动服务
rabbitmq-service.bat start


关闭服务
rabbitmq-service.bat stop

查看服务状态
rabbitmqctl status


服务管理可视化(插件形式)

#查看已安装的插件列表
rabbitmq-plugins.bat list


#开启服务管理插件
rabbitmq-plugins.bat enable rabbitmq_management


#访问服务器
http://localhost:15672
服务端口:5672,管理后台端口:15672
用户名&密码:guest

远程访问

RabbitMQ默认只有一个guest帐号,guest帐号只能在RabbitMQ安装服务器上登录,在其它服务器用guest登录提示User can only log in via localhost。

这个情况的最佳解决办法是添加一个新的帐号

进入RabbitMQ安装目录 ..\RabbitMQ Server\rabbitmq_server-3.9.13\sbin

#第一步:添加 admin 用户并设置密码
rabbitmqctl add_user admin 123456
#第二步:添加 admin 用户为administrator角色
rabbitmqctl set_user_tags admin administrator
#第三步:设置 admin 用户的权限,指定允许访问的vhost以及write/read
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
#第四步:查看vhost(/)允许哪些用户访问
rabbitmqctl list_permissions -p /
#第五步:查看用户列表
rabbitmqctl list_users
#第六步:配置允许远程访问的用户,rabbitmq的guest用户默认不允许远程主机访问。
在windows 下的 rabbitmq安装文件下的etc文件下的配置文件添加以下

[
    {rabbit, [{tcp_listeners, [5672]}, {loopback_users, ["账户名"]}]}
].

 

AMQP

AMQP(advanced message queuing protocol):一种协议(高级消息队列协议,也是消息代理规范),规范了网络交换的数据格式,兼容JMS
优点:具有跨平台性,服务器供应商,生产者,消费者可以使用不同的语言来实现
AMQP消息模型
direct exchange
fanout exchange
topic exchange
headers exchange
system exchange
AMQP消息种类:byte[]
AMQP实现:RabbitMQ、StormMQ、RocketMQ
 

 RabbitMQ Tutorials — RabbitMQ

简单队列模型

官方的HelloWorld是基于最基础的消息队列模型来实现的,只包括三个角色:

publisher:消息发布者,将消息发送到队列queue

queue:消息队列,负责接受并缓存消息

consumer:订阅队列,处理队列中的消息

 详见 mq-demo1

SpringAMQP

SpringAmqp的官方地址:https://spring.io/projects/spring-amqp

利用SpringAMQP实现HelloWorld中的基础消息队列功能

流程如下:

1 在父工程中引入spring-amqp的依赖

   <!--AMQP依赖,包含RabbitMQ-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
  • 在publisher服务中利用RabbitTemplate发送消息到simple.queue这个队列
#application.yml,添加mq连接信息:
spring:
  rabbitmq:
    host: 192.168.125.118 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: admin
    password: admin
    virtual-host: /


#新建一个测试类,编写测试方法:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSendMessage2SimpleQueue() {
        String queueName = "simple.queue";
        String message = "hello, spring amqp!";
        rabbitTemplate.convertAndSend(queueName, message);
    }
}
  • 在consumer服务中编写消费逻辑,绑定simple.queue这个队列
#application.yml,添加mq连接信息:
spring:
  rabbitmq:
    host: 192.168.125.118 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: admin
    password: admin
    virtual-host: /


#在consumer服务中新建一个类,编写消费逻辑:

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalTime;
import java.util.Map;

@Component
public class SpringRabbitListener {
 
    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueue1(String msg) throws InterruptedException {
        System.out.println("消费者1接收到消息:【" + msg + "】" );
        Thread.sleep(20);
    }
}

注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能

Work queue,工作队列,可以提高消息处理速度,避免队列消息堆积 

 模拟WorkQueue,实现一个队列绑定多个消费者

在publisher服务中定义测试方法,每秒产生50条消息,发送到simple.queue

   @Test
    public void testSendMessage2WorkQueue() throws InterruptedException {
        String queueName = "simple.queue";
        String message = "hello, message__";
        for (int i = 1; i <= 50; i++) {
            rabbitTemplate.convertAndSend(queueName, message + i);
            Thread.sleep(20);
        }
    }

在consumer服务中定义两个消息监听者,都监听simple.queue队列


import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.time.LocalTime;

@Component
public class SpringRabbitListener {


    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueue1(String msg) throws InterruptedException {
        System.out.println("消费者1接收到消息:【" + msg + "】" + LocalTime.now());
        Thread.sleep(20);
    }

    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueue2(String msg) throws InterruptedException {
        System.err.println("消费者2........接收到消息:【" + msg + "】" + LocalTime.now());
        Thread.sleep(200);
    }
 
}

消费者1每秒处理50条消息,消费者2每秒处理10条消息

     细心观察打印日志发现消息被处理的时间合计值超出预设时间,这是因为RABBIT 消息预取机制造成的(当有大量的消息到达消息队列时,队列会提前把消息拿过来,这就造成了总时长变长了),要解决这个问题,可以设置preFetch来控制预取消息上限。

修改application.yml文件,设置preFetch这个值,可以控制预取消息的上限:
spring:
  rabbitmq:
    host: 192.168.125.118 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: admin
    password: admin
    virtual-host: /
    listener:
      simple:
        prefetch: 1   # 每次只能获取一条消息,处理完成才能获取下一个消息

以上案例的共同特点是:一个消息只能被一个消费者消费。

发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入exchange(交换机).

常见exchange类型包括:

Fanout:广播

Direct:路由

Topic:话题

 注意:exchange负责消息路由,路由失败则消息丢失,exchange不存储数据

Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue 

SpringAMQP演示FanoutExchange的使用

实现思路如下:

1 在consumer服务中,利用代码声明队列、交换机,并将两者绑定

    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("mqchange.fanout");
    }

    @Bean
    public Queue fanoutQueue1(){
       return   new Queue("fanout.queue1");
    }
    @Bean
    public Queue fanoutQueue2(){
       return   new Queue("fanout.queue2");
    }

    @Bean
    public Binding fanoutBinging1(FanoutExchange fanoutExchange,Queue fanoutQueue1){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }
    @Bean
    public Binding fanoutBinging2(FanoutExchange fanoutExchange,Queue fanoutQueue2){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }

2 在consumer服务中,编写两个消费者方法,分别监听fanout.queue1和fanout.queue2

    @RabbitListener(queues = "fanout.queue1")
    public void listenerFanoutQueue1(String msg)  {
        System.out.println("AMQP消费者接收队列 FanoutQueue1的信息:==》 "+msg);
    }

    @RabbitListener(queues = "fanout.queue2")
    public void listenerFanoutQueue2(String msg)  {
        System.err.println("AMQP消费者接收队列 FanoutQueue2的信息:==》 "+msg);
    }

3 在publisher中编写测试方法,向mq.fanout发送消息

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testPublish2SimpleQueue(){
        String exchangeName="mqchange.fanout";
        String message="hello rabbitmq";
        rabbitTemplate.convertAndSend(exchangeName,"",message);
    }

发布订阅-DirectExchange

Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。

发布者发送消息时,指定消息的RoutingKey

Exchange将消息路由到BindingKey与消息RoutingKey一致的队列

 利用SpringAMQP演示DirectExchange的使用

发布订阅-TopicExchange

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值