消息队列RabbitMQ、ActiveMQ、Kafka

本文介绍了消息队列的基本概念、AMQP协议以及核心概念,强调了消息队列在应用耦合、异步处理、高可用性等方面的作用。详细阐述了RabbitMQ、ActiveMQ等常用消息队列框架,并探讨了不同类型的交换机、消息确认机制以及拒绝消息的处理方式。最后,提到了在SpringBoot中使用RabbitMQ的实践。
消息队列

消息队列(Message queue)是一种进程间或同一进程的不同线程间的通信方式,消息队列提供了异步的通信协议,也就是说消息的发送者和接收者不需要同时与消息队列交互,消息会保存在队列中,直到接收者取回它。队列可以用链表来实现,它又分为链式队列、循环队列、双端队列等。

功能特点: 应用耦合、异步消息、削峰/限流、高可用性(集群/分布式)

常用消息队列 ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ

AMQP协议概念

AMQP(高级消息队列协议)是一个网络协议。它支持符合要求的客户端应用(application)和消息中间件代理(messaging middleware broker)之间进行通信。通过规范化协议,不同的消息队列框架可以根据协议用不同的方式来实现。

核心概念

消息(message)被发布者(publisher)发送给交换机(exchange),交换机常常被比喻成邮局或者邮箱。然后交换机将收到的消息根据路由规则分发给绑定的队列(queue)。最后AMQP代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。
在这里插入图片描述

发布者(publisher)发布消息时可以给消息指定各种消息属性(message meta-data)。有些属性有可能会被消息代理(brokers)使用,然而其他的属性则是完全不透明的,它们只能被接收消息的应用所使用。

为了提高可靠性。AMQP模块包含了一个消息确认(message acknowledgements)的概念:当一个消息从队列中投递给消费者后(consumer),消费者会通知一下消息代理(broker),这个可以是自动的也可以由处理消息的应用的开发者执行。当“消息确认”被启用的时候,消息代理不会完全将消息从队列中删除,直到它收到来自消费者的确认回执(acknowledgement)。

在某些情况下,例如当一个消息无法被成功路由时,消息或许会被返回给发布者并被丢弃。或者,如果消息代理执行了延期操作,消息会被放入一个所谓的死信队列中。此时,消息发布者可以选择某些参数来处理这些特殊情况。

消息队列包括两种模式

点对点模式(point to point):生产者将消息推送到队列总,然后消费者从队列中取出消息,队列中不再存储消息,也即消息一旦被消费就不会存在重复消费的问题。
在这里插入图片描述

  • 每个消息只有一个接收者(Consumer)(即一旦被消费,消息就不再在消息队列中);
  • 发送者和接收者间没有依赖性,发送者发送消息之后,不管有没有接收者在运行,都不会影响到发送者下次发送消息;
  • 接收者在成功接收消息之后需向队列应答成功,以便消息队列删除当前接收的消息;

发布/订阅模式(publish/subscribe,topic):发布者将消息发送到Topic,系统将这些消息传递给多个订阅者,也即一个消息可以被多个消费者消费。因而消费者需要提前订阅Topic主题,并保持在线运行

在这里插入图片描述

常用交换机类型

直连型交换机(direct exchange) 是根据消息携带的路由键(routing key)将消息投递给对应队列的。直连交换机用来处理消息的单播路由(unicast routing)

扇型交换机(fanout exchange) 将消息路由给绑定到它身上的所有队列,而不理会绑定的路由键。如果N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的拷贝分别发送给这所有的N个队列。扇型用来交换机处理消息的广播路由(broadcast routing)。

主题交换机(topic exchanges) 通过对消息的路由键和队列到交换机的绑定模式之间的匹配,将消息路由给一个或多个队列。主题交换机经常用来实现各种分发/订阅模式及其变种。主题交换机通常用来实现消息的多播路由(multicast routing)。

AMQP中的队列(queue)跟其他消息队列或任务队列中的队列是很相似的:它们存储着即将被应用消费掉的消息。持久化队列(Durable queues)会被存储在磁盘上,当消息代理(broker)重启的时候,它依旧存在。没有被持久化的队列称作暂存队列(Transient queues)。绑定(Binding)是交换机(exchange)将消息(message)路由给队列(queue)所需遵循的规则。如果要指示交换机“E”将消息路由给队列“Q”,那么“Q”就需要与“E”进行绑定。

拒绝消息

当一个消费者接收到某条消息后,处理过程有可能成功,有可能失败。应用可以向消息代理表明,本条消息由于“拒绝消息(Rejecting Messages)”的原因处理失败了(或者未能在此时完成)。当拒绝某条消息时,应用可以告诉消息代理如何处理这条消息——销毁它或者重新放入队列。当此队列只有一个消费者时,请确认不要由于拒绝消息并且选择了重新放入队列的行为而引起消息在同一个消费者身上无限循环的情况发生**(死信)**。

常用消息队列框架

RabbitMQ

rabbit官网使用指引 https://www.rabbitmq.com/getstarted.html

docker 安装rabbitMq

#命令
sudo docker run -d --name rabbitmq -h rabbitmq -p 5672:5672 -v /var/lib/rabbitmq:/var/lib/rabbitmq registry.docker-cn.com/library/rabbitmq:3.7

#搜索安装rabbitmq docker镜像
docker search rabbitMq
docker pull docker.io/rabbitmq:3.8-management

#运行镜像 运行容器并将端口映射到主机 rabbitMq默认要使用15672为其web端界面访问时端口,5672为数据通信端口
docker images 
docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672  imageId 

#查看运行情况 查看容器日志
docker ps 
docker logs -f containerId 

#主机Ip:15672可以访问rabbitMq的Web端管理页面,默认用户名密码都为guest
#查看修改rabbit用户
#进入容器shell
docker exec -i -t containerId bin/bash
#查看所有用户
rabbitmqctl list_users
#新增root用户 添加用户,用户名为root,密码为123456
rabbitmqctl add_user root 123456 
#赋予root用户所有权限
rabbitmqctl set_permissions -p / root ".*" ".*" ".*" 
#赋予root用户administrator角色
rabbitmqctl set_user_tags root administrator
springboot中使用rabbitmq

rabbitmq支持对象实体消息发送

//1、引入pom
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-amqp</artifactId>
	</dependency>
//2、配置properties
spring.rabbitmq.host=49.232.34.66
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
//3、编写配置类
@Configuration
public class TopicRabbitConfig {

    final static String message = "topic.message";
   
   //创建队列
    @Bean
    public Queue queueMessage() {
        return new Queue(TopicRabbitConfig.message);
    }

	//创建交换机
    @Bean
    TopicExchange exchange() {
        return new TopicExchange("topicExchange");
    }

	//绑定交换机,订阅主题
    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }
  
}
//4、监听队列(消费者)
@Component
@RabbitListener(queues = "topic.message")
public class TopicReceiver {

    @RabbitHandler
    public void process(String message) {
        System.out.println("Topic Receiver1  : " + message);
    }
}
//5、发送消息(生产者)
@Component
public class TopicSender {

	@Autowired
	private AmqpTemplate rabbitTemplate;
    
	public void send1() {
		String context = "hi, i am message 1";
		System.out.println("Sender : " + context);
		this.rabbitTemplate.convertAndSend("topicExchange", "topic.message", context);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值