java:brew安装rabbitmq以及简单示例

什么是消息队列mq

可以看我之前写的这篇 消息队列MQ

rabbitmq简介

RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。

brew安装rabbitmq

1、安装
官方文档

shell 复制代码
brew install rabbitmq

这是安装的 log

shell 复制代码
Management UI: http://localhost:15672
Homebrew-specific docs: https://rabbitmq.com/install-homebrew.html

To start rabbitmq now and restart at login:
  brew services start rabbitmq
Or, if you don't want/need a background service you can just run:
  CONF_ENV_FILE="/opt/homebrew/etc/rabbitmq/rabbitmq-env.conf" /opt/homebrew/opt/rabbitmq/sbin/rabbitmq-server

2、打开 http://localhost:15672

默认的用户名密码都是 guest,登录后可以在 Admin 那一列菜单内添加自己的用户

权限

超级管理员(administrator)

可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。

监控者(monitoring)

可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)

策略制定者(policymaker)

可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。

普通管理者(management)

仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。

其他

无法登陆管理控制台,通常就是普通的生产者和消费者。

创建虚拟主机(Virtual Hosts)

为了让各个用户可以互不干扰的工作,RabbitMQ添加了虚拟主机(Virtual Hosts)的概念。其实就是一个独立的访问路径,不同用户使用不同路径,各自有自己的队列、交换机,互相不会影响。

交换机类型

1. 直连交换机(Direct Exchange)

特点:

  • 基于路由键(Routing Key)的完全匹配来路由消息。

应用场景:

  • 当消息需要明确指定到某个队列时,使用直连交换机。

举例说明:

  • 假设有一个订单处理系统,其中包含"订单处理"和"订单审核"两个队列。生产者发送一个消息时,指定路由键为"order.process",那么只有绑定了该路由键的"订单处理"队列会收到消息。如果指定路由键为"order.review",则只有"订单审核"队列会收到消息。

2. 扇形交换机(Fanout Exchange)

特点:

  • 将消息广播到所有绑定到它的队列,忽略路由键。如果N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的发送给这所有的N个队列

应用场景:

  • 当需要将消息发送给多个队列,且每个队列都需要接收到相同消息的副本时,使用扇出交换机。

举例说明:

  • 假设有一个实时新闻发布系统,包含"新闻订阅者A"和"新闻订阅者B"两个队列。生产者发布一条新闻消息到扇出交换机,那么这条消息将被同时发送到"新闻订阅者A"和"新闻订阅者B"两个队列,实现广播效果。

3. 主题交换机(Topic Exchange)

特点:

  • 基于路由键和通配符(*和#)的模糊匹配来路由消息。

应用场景:

  • 当需要根据消息的不同类型或属性将其路由到不同的队列时,使用主题交换机。

举例说明:

  • 假设有一个日志系统,包含"error.log"、"info.log"和"debug.log"三个队列。生产者发送一条错误日志消息,路由键为"system.error"。此时,绑定了"*.error"或"system.#"的队列将接收到这条消息,因此"error.log"队列会收到它,而"info.log"和"debug.log"则不会(除非它们也绑定了匹配的路由键)。

* (星号) 用来表示一个单词 (必须出现的)
# (井号) 用来表示任意数量(零个或多个)单词

通配的绑定键是跟队列进行绑定的,举个小例子

队列Q1 绑定键为*.TT.* 队列Q2绑定键为 TT.#

如果一条消息携带的路由键为 A.TT.B,那么队列Q1将会收到;

如果一条消息携带的路由键为TT.AA.BB,那么队列Q2将会收到;

4. 头部交换机(Headers Exchange)

特点:

  • 基于消息的头部信息进行匹配,而不是路由键。

应用场景:

  • 当需要根据消息的复杂属性进行路由时,使用头部交换机。这种交换机类型使用较少,因为它需要更复杂的匹配逻辑。

举例说明(假设场景):

  • 假设有一个消息处理系统,其中消息具有多个头部属性,如"priority"(优先级)、"type"(类型)等。生产者发送一条高优先级的紧急消息,并设置相应的头部属性。此时,只有那些设置了匹配这些头部属性(如"priority=high")的队列才会接收到这条消息。

RabbitMQ的工作原理

组成部分说明:

Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue

Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。

Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费者

Producer:消息生产者,即生产方客户端,生产方客户端将消息发送

Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。

生产者发送消息流程:

1、生产者和Broker建立TCP连接。

2、生产者和Broker建立通道。

3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。

4、Exchange将消息转发到指定的Queue(队列)

消费者接收消息流程:

1、消费者和Broker建立TCP连接

2、消费者和Broker建立通道

3、消费者监听指定的Queue(队列)

4、当有消息到达Queue时Broker默认将消息推送给消费者。

5、消费者接收到消息。

6、ack回复

使用

基本配置

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
shell 复制代码
spring.application.name=zy-rabbitmq

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=xxx
spring.rabbitmq.password=xxx
#虚拟host 可以不设置,使用server默认host
spring.rabbitmq.virtual-host: JCcccHost

直连交换机示例

创建一个配置文件

java 复制代码
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class DirectRabbitConfig {
 
    //队列 起名:TestDirectQueue
    @Bean
    public Queue TestDirectQueue() {
        // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
        // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
        // return new Queue("TestDirectQueue",true,true,false);
 
        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("TestDirectQueue",true);
    }
 
    //Direct交换机 起名:TestDirectExchange
    @Bean
    DirectExchange TestDirectExchange() {
      //  return new DirectExchange("TestDirectExchange",true,true);
        return new DirectExchange("TestDirectExchange",true,false);
    }
 
    //绑定  
    //将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
    @Bean
    Binding bindingDirect() {
        return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
    }
     
    @Bean
    DirectExchange lonelyDirectExchange() {
        return new DirectExchange("lonelyDirectExchange");
    }
}

写个简单的接口进行消息推送(根据需求也可以改为定时任务等等,具体看需求)

java 复制代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@RestController
public class SendMessageController {

    //使用RabbitTemplate,这提供了接收/发送等等方法
    @Autowired
    RabbitTemplate rabbitTemplate;  
 
    @GetMapping("/sendDirectMessage")
    public String sendDirectMessage() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "test message, hello!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        //将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", map);
        return "ok";
    }
}


可以看到消息已经推送到rabbitMq服务器上面了。接下来要消费这个消息了。一般来说要开启另一个服务来消费了,但是我们是练习就在当前服务进行消费。

然后是创建消息接收监听类

java 复制代码
@Component
//监听的队列名称 TestDirectQueue
@RabbitListener(queues = "TestDirectQueue")
public class DirectReceiver {
 
    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("DirectReceiver消费者收到消息  : " + testMessage.toString());
    }
 
}

运行项目,就把这个消息消费掉了。

扇形交换机、主题交换机

和上面的差不多,就先不写了

参考资料

https://blog.csdn.net/weixin_42039228/article/details/123493937

相关推荐
坐吃山猪20 小时前
SpringBoot01-配置文件
java·开发语言
我叫汪枫21 小时前
《Java餐厅的待客之道:BIO, NIO, AIO三种服务模式的进化》
java·开发语言·nio
yaoxtao21 小时前
java.nio.file.InvalidPathException异常
java·linux·ubuntu
Swift社区1 天前
从 JDK 1.8 切换到 JDK 21 时遇到 NoProviderFoundException 该如何解决?
java·开发语言
DKPT1 天前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy1 天前
JVM——Java虚拟机学习
java·jvm·学习
seabirdssss1 天前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续1 天前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben0441 天前
ReAct模式解读
java·ai