RabbitMQ特性介绍和使用案例

news2024/11/24 17:25:27

❤ 作者主页:李奕赫揍小邰的博客
❀ 个人介绍:大家好,我是李奕赫!( ̄▽ ̄)~*
🍊 记得点赞、收藏、评论⭐️⭐️⭐️
📣 认真学习!!!🎉🎉

文章目录

      • RabbitMQ特性
      • 案例
        • springboot+rabbitmq

 

RabbitMQ特性

AMQP(高级消息队列协议) 是一个异步消息传递所使用的应用层协议规范,作为线路层协议,而不是API(例如JMS),AMQP 客户端能够无视消息的来源任意发送和接受信息。AMQP的原始用途只是为金融界提供一个可以彼此协作的消息协议,而现在的目标则是为通用消息队列架构提供通用构建工具。因此,面向消息的中间件 (MOM)系统,例如发布/订阅队列,没有作为基本元素实现。反而通过发送简化的AMQ实体,用户被赋予了构建例如这些实体的能力。这些实体也是规范的一 部分,形成了在线路层协议顶端的一个层级:AMQP模型。这个模型统一了消息模式,诸如之前提到的发布/订阅,队列,事务以及流数据,并且添加了额外的特性,例如更易于扩展,基于内容的路由。

AMQP当中有四个概念非常重要

  1. virtual host,虚拟主机
  2. exchange,交换机
  3. queue,队列
  4. binding,绑定

一个虚拟主机持有一组交换机、队列和绑定。

为什么需要多个虚拟主机呢?因为RabbitMQ当中,用户只能在虚拟主机的粒度进行权限控制。因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个RabbitMQ服务器都有一个默认的虚拟主机/

何谓虚拟主机(virtual host),交换机(exchange),队列(queue)和绑定(binding)

队列(Queues)是你的消息(messages)的终点,可以理解成装消息的容器。消息就一直在里面,直到有客户端(也就是消费者,Consumer)连接到这个队列并且将其取走为止。不过,也可以将一个队列配置成这样的:一旦消息进入这个队列,此消息就被删除。

队列是由消费者(Consumer)通过程序建立的,不是通过配置文件或者命令行工具。这没什么问题,如果一个消费者试图创建一个已经存在的队列,RabbitMQ会直接忽略这个请求。因此我们可以将消息队列的配置写在应用程序的代码里面。

而要把一个消息放进队列前,需要有一个交换机(Exchange)。

交换机(Exchange)可以理解成具有路由表的路由程序。每个消息都有一个称为路由键(routing key)的属性,就是一个简单的字符串。交换机当中有一系列的绑定(binding),即路由规则(routes)。(例如,指明具有路由键 “X” 的消息要到名为timbuku的队列当中去。)

消费者程序(Consumer)要负责创建你的交换机。交换机可以存在多个,每个交换机在自己独立的进程当中执行,因此增加多个交换机就是增加多个进程,可以充分利用服务器上的CPU核以便达到更高的效率。例如,在一个8核的服务器上,可以创建5个交换机来用5个核,另外3个核留下来做消息处理。类似的,在RabbitMQ的集群当中,你可以用类似的思路来扩展交换机一边获取更高的吞吐量。

交换机如何判断要把消息送到哪个队列?你需要路由规则,即绑定(binding)。一个绑定就是一个类似这样的规则:将交换机“desert(沙漠)”当中具有路由键“阿里巴巴”的消息送到队列“hideout(山洞)”里面去。换句话说,一个绑定就是一个基于路由键将交换机和队列连接起来的路由规则。例如,具有路由键“audit”的消息需要被送到两个队列,“log-forever”和“alert-the-big-dude”。要做到这个,就需要创建两个绑定,每个都连接一个交换机和一个队列,两者都是由“audit”路由键触发。在这种情况下,交换机会复制一份消息并且把它们分别发送到两个队列当中。交换机不过就是一个由绑定构成的路由表。

交换机有多种类型。他们都是做路由的,但是它们接受不同类型的绑定。为什么不创建一种交换机来处理所有类型的路由规则呢?因为每种规则用来做匹配分子的CPU开销是不同的。例如,一个“topic”类型的交换机试图将消息的路由键与类似“dogs.*”的模式进行匹配。匹配这种末端的通配符比直接将路由键与“dogs”比较(“direct”类型的交换机)要消耗更多的CPU。如果你不需要“topic”类型的交换机带来的灵活性,你可以通过使用“direct”类型的交换机获取更高的处理效率。那么有哪些类型,他们又是怎么处理的呢?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FpX38whq-1692879359179)(asset\rabbitmq-exchange.png)]

Exchange Direct

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nilADBxt-1692879359180)(asset\rabbitmq-direct.png)]

Exchange Fanout

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cEiXfIFB-1692879359181)(asset\rabbitmq-fanout.png)]

Exchange Topic

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SfvW9P0P-1692879359181)(asset\rabbitmq-topic.png)]

在这里插入图片描述

持久化

你花了大量的时间来创建队列、交换机和绑定,然后,服务器程序挂了。你的队列、交换机和绑定怎么样了?还有,放在队列里面但是尚未处理的消息们呢?

如果你是用默认参数构造的这一切的话,那么,他们都灰飞烟灭了。RabbitMQ重启之后会干净的像个新生儿。你必须重做所有的一切,亡羊补牢,如何避免将来再度发生此类杯具?

队列和交换机有一个创建时候指定的标志durable。durable的唯一含义就是具有这个标志的队列和交换机会在重启之后重新建立,它不表示说在队列当中的消息会在重启后恢复。那么如何才能做到不只是队列和交换机,还有消息都是持久的呢?

但是首先需要考虑的问题是:是否真的需要消息的持久化?如果需要重启后消息可以回复,那么它需要被写入磁盘。但即使是最简单的磁盘操作也是要消耗时间的。所以需要衡量判断。

当你将消息发布到交换机的时候,可以指定一个标志“Delivery Mode”(投递模式)。根据你使用的AMQP的库不同,指定这个标志的方法可能不太一样。简单的说,就是将Delivery Mode设置成2,也就是持久的(persistent)即可。一般的AMQP库都是将Delivery Mode设置成1,也就是非持久的。所以要持久化消息的步骤如下:

  1. 将交换机设成 durable。
  2. 将队列设成 durable。
  3. 将消息的 Delivery Mode 设置成2 。

绑定(Bindings)怎么办?绑定无法在创建的时候设置成durable。没问题,如果你绑定了一个durable的队列和一个durable的交换机,RabbitMQ会自动保留这个绑定。类似的,如果删除了某个队列或交换机(无论是不是durable),依赖它的绑定都会自动删除。

注意:

  • RabbitMQ 不允许你绑定一个非坚固(non-durable)的交换机和一个durable的队列。反之亦然。要想成功必须队列和交换机都是durable的。
  • 一旦创建了队列和交换机,就不能修改其标志了。例如,如果创建了一个non-durable的队列,然后想把它改变成durable的,唯一的办法就是删除这个队列然后重现创建。因此,最好仔细检查创建的标志。

案例

springboot+rabbitmq

  • pom.xml
<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit-test</artifactId>
			<scope>test</scope>
		</dependency>
</dependencies>
  • application.properties
server.port=8181

#rabbitmq配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=wt
spring.rabbitmq.password=123456
spring.rabbitmq.virtual-host=/
  • 实体类
package cn.edu.entity;

import java.io.Serializable;

public class User implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int id;
	private String userName;
	private String userPassword;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserPassword() {
		return userPassword;
	}
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", userName=" + userName + ", userPassword=" + userPassword + "]";
	}
	
}
  • rabbitmq config
package cn.edu.config;

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.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 实例化
 *    交换机对象
 *    队列对象
 *    绑定对象
 * @author Administrator
 *
 */
@Configuration
public class RabbitMqConfig {
	@Autowired
	private RabbitTemplate rabbitTemplate;
	
	
	@Bean(name="rabbitAdmin")
	public RabbitAdmin getRabbitAdmin() {
		RabbitAdmin rabbitAdmin=new RabbitAdmin(this.rabbitTemplate.getConnectionFactory());
		rabbitAdmin.setAutoStartup(true);
		return rabbitAdmin;
	}
	@Bean(name="queue1")
	public Queue queue1(@Qualifier("rabbitAdmin") RabbitAdmin rabbitAdmin) {
		Queue queue=new Queue("queue1",true);
		return queue;
	}
	@Bean(name="queue2")
	public Queue queue2() {
		Queue queue=new Queue("queue2",true);
		return queue;
	}
	
	@Bean
	public DirectExchange exchange() {
		DirectExchange directExchange=new DirectExchange("directExchangeName");
		return directExchange;
	}
	
	@Bean
	public Binding bind01(
			@Qualifier("queue1") Queue messageQueue,
			@Qualifier("exchange") DirectExchange directExchange) {
		Binding binding=BindingBuilder.bind(messageQueue)
				                      .to(directExchange)
				                      .with("item1");
	    return binding;
	}
	@Bean
	public Binding bind02(
			@Qualifier("queue2") Queue objectQueue,
			@Qualifier("exchange") DirectExchange directExchange) {
		Binding binding=BindingBuilder.bind(objectQueue)
				                      .to(directExchange)
				                      .with("item2");
	    return binding;
	}
}
  • 生产者类
package cn.edu.controller;

import org.springframework.amqp.core.AmqpTemplate;
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 cn.tedu.entity.User;

@RestController
public class UserController {
	//ReabbitTemplate实现自AmqpTemplate
	
	@Autowired
	private RabbitTemplate rabbitTempate;
	
	@Autowired
	private AmqpTemplate amqpTempate;
	
	/**
	 * 演示给队列发送字符串
	 * @return
	 */
	@GetMapping("/sendMessage")
	public String sendMessage() {
		//把消息(aaaaaaaaaaaaa)发送给直接交换机(directExchangeName),使用的是路由key(item1),路由key关联了一个队列
		this.rabbitTempate.convertAndSend("directExchangeName","item1","aaaaaaaaaaaaa");
		//没有指定交换机,使用的就是默认交换机
		//this.rabbitTempate.convertAndSend("item1","aaaaaaaaaaaaa");
		return "success";
	}
	/**
	 * 演示给队列发送对象
	 * @return
	 */
	@GetMapping("/sendObject")
	public String sendObject() {
		User user=new User();
		user.setId(1);
		user.setUserName("张三");
		user.setUserPassword("123");
		//把消息(user对象)发送给直接交换机(directExchangeName),使用的是路由key(item2),路由key关联了一个队列
		this.rabbitTempate.convertAndSend("directExchangeName","item2",user);
		return "success";
	}
}
  • 消费者
package cn.edu.mqconsumer;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import cn.tedu.entity.User;

/**
 * 用来消费队列中的数据
 * @author Administrator
 *
 */
@Component
public class ConsumerObject {
	/**
	 * 用来监听消费queue1中的数据
	 * @param msg
	 */
	@RabbitListener(queues = {"queue1"})
	@RabbitHandler
	public void process01(Message msg) {
		System.out.print(msg.getClass()+"消费者消费队列1中的字符串消息");
		System.out.println(new String(msg.getBody()));
		
	}
	
	
	/**
	 * 用来监听消费queue2中的数据
	 * @param msg
	 */
	@RabbitListener(queues = {"queue2"})
	@RabbitHandler
	public void process02(Message msg) {
		try {
			System.out.print(msg.getClass()+"消费者消费队列2中的User对象的消息");
			byte[] bytes=msg.getBody();
			//把字节数据转换成具体的User对象
			ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
			//把字节输入流转换成对象输入流
			ObjectInputStream ois=new ObjectInputStream(bais);
			User user=(User)ois.readObject();
			System.out.println(user.getId()+"   "+user.getUserName()+"   "+user.getUserPassword());
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
  • 主启动
package cn.edu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestspringbootRabbitmqApplication {

	public static void main(String[] args) {
		SpringApplication.run(TestspringbootRabbitmqApplication.class, args);
	}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/923122.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

张博《冰雪尖刀连》饰梅生 剧抛脸名不虚传

“《冰雪尖刀连》又燃又感动&#xff01;”“根本看不够&#xff01;”由著名导演执导&#xff0c;实力派演员主演的抗美援朝战争剧《冰雪尖刀连》正在总台央视一套热播&#xff0c;全网络平台同步更新中。该剧讲述了“钢七连”战士为了保家卫国远赴异国战场&#xff0c;爬冰卧…

设计模式——装饰器模式

装饰器模式 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于结构型模式&#xff0c;它是作为现有的类的一个包装。 装饰器模式通过将对象包装在装饰器类中&#xff0c;以便动态…

前端页面常见的布局分享

前端页面常见的布局分享 一、css盒模型 页面中的每一个元素都被看做一个矩形盒子。它包括&#xff1a;外边距、边框、内边距以及实际的内容。 网页设计中常听的属性名&#xff1a;内容(content)、填充(padding)、边框(border)、边界(margin)&#xff0c;CSS盒子模型都具备这些…

为什么说ChatGPT地位难保

似乎可以说&#xff0c;从ChatGPT推出以来&#xff0c;OpenAI一直是生成式人工智能的王者。但这种状况可能持续不了太久了。 自11月面世以来&#xff0c;OpenAI的聊天机器人颠覆了教学、写作、科技等多个领域[1]。它把世界上最大的科技公司如Meta和谷歌打了个措手不及&#x…

HJ31 单词倒排 题解

题目描述&#xff1a;单词倒排_牛客题霸_牛客网 (nowcoder.com) 对字符串中的所有单词进行倒排。 1、构成单词的字符只有26个大写或小写英文字母&#xff1b; 2、非构成单词的字符均视为单词间隔符&#xff1b; 3、要求倒排后的单词间隔符以一个空格表示&#xff1b;如果原字符…

如何拼接两个视频在一起?

如何拼接两个视频在一起&#xff1f;在度过一个美好周末的时候&#xff0c;我和朋友一起拍摄了两组视频&#xff0c;准备将两个视频合并成一个并发布到朋友圈。这个想法非常棒&#xff0c;但是我在第一步就遇到了麻烦&#xff1a;如何将这两个视频拼接在一起&#xff1f;这听起…

MyBatis分页思想和特殊字符

目录 一、MyBatis分页思想 1.1 使用场景 1.2 代码演示 二、MyBatis特殊字符 2.1代码演示 一、MyBatis分页思想 1.1 使用场景 Mybatis分页应用场景&#xff1a; MyBatis是一个Java持久层框架&#xff0c;它提供了一种将SQL查询和结果映射到Java对象的简单方式。分页是MyBa…

【LeetCode】面试题总结 消失的数字 最小k个数

1.消失的数字 两种思路 1.先升序排序&#xff0c;再遍历并且让后一项与前一项比较 2.转化为数学问题求等差数列前n项和 &#xff08;n的大小为数组的长度&#xff09;&#xff0c;将根据公式求得的应有的和数与数组中实际的和作差 import java.util.*; class Solution {public …

龙迅半导体,LT9611 MIPIDSI/CSI转HDMI,双端口MIPI接收,HDMI支持4K30HZ,免费提供完善的资料和选型推荐

龙迅LT9611 1.描述&#xff1a; LT9611 MIPIDSI/CSI到HDMI1.4桥具有双端口MIPID-PHY接收器前端配置&#xff0c;每个端口有4个数据通道&#xff0c;每个数据通道运行2Gbps&#xff0c;最大输入带宽为16Gbps。该桥提供了一个HDMI数据输出与可选的S/PDIF或8通道I2S串行音频输入…

Excel变天!微软把Python「塞」进去了,直接可搞机器学习

量子位 | 公众号 QbitAI 喜大普奔&#xff01; 微软把Python弄进Excel了&#xff01; 搭建一个机器学习天气预测模型&#xff0c;在Excel里即可实现。 而且无需任何设置&#xff0c;在单元格里输入“PY”&#xff0c;就能开搞。 数据清理、预测分析、可视化等等任务&#xf…

Harbor平台离线搭建

之前我有写过如何搭建harbor以及配置harbor&#xff0c;本文主要讲一下在不联网的情况下如何搭建Harbor平台。 环境&#xff1a;centos 7.9 docker版本&#xff1a;20.10.17 harbor版本&#xff1a;v1.10.10 一、离线安装docker 安装包官方地址&#xff1a;Index of linux/sta…

麒麟系统上安装 MySQL 8.0.24

我介绍一下在麒麟系统上安装 MySQL 8.0.24 的详细步骤&#xff0c;前提是您已经下载了 mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz 安装包。其实安装很简单&#xff0c;但是有坑&#xff0c;而且问题非常严重&#xff01;由于麒麟系统相关文章博客较少&#xff0c;导致遇到了…

[MyBatis系列③]动态SQL

目录 1、简介 2、if标签 3、foreach标签 4、SQL抽取 ⭐MyBatis系列①&#xff1a;增删改查 ⭐MyBatis系列②&#xff1a;两种Dao开发方式 1、简介 开发中在MyBatis映射文件配置SQL语句&#xff0c;但是前面配置的都是比较简单的&#xff0c;不涉及稍复杂的业务场景。想要应…

守护进程(精灵进程)

目录 前言 1.如何理解前台进程和后台进程 2.守护进程的概念 3.为什么会存在守护进程 4.如何实现守护进程 5.测试 总结 前言 今天我们要介绍的是关于守护进程如何实现&#xff0c;可能有小伙伴第一次听到守护进程这个概念&#xff0c;感觉很懵&#xff0c;知道进程的概念&…

实验八 网卡驱动移植

【实验目的】 掌握 Linux 内核配置的基本方法&#xff0c;完成对网卡驱动、NFS 等相关功能的配置 【实验环境】 ubuntu 14.04 发行版FS4412 实验平台交叉编译工具&#xff1a;arm-none-linux-gnueabi- 【注意事项】 实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行&…

基于labview设备状态监测和故障诊断(一)NI软硬件介绍

随着近代工业逐步向机电一体化方向发展。设备的自动化、智能化、大型化与复杂 化程度的不断提高&#xff0c;设备发生故障给企业所带来的经济损失越来越大&#xff0c;因此对设备的运 行状况进行实时监测和故障诊断势在必行。可以这样说&#xff0c;机械设备的工作状况监测和…

C++设计模式(工厂模式)

文章目录 前言一、什么是工厂模式二、简单工厂模式三、简单工厂模式优点和缺点四、简单工厂适用场景五、简单工厂类的使用总结 前言 本篇文章正式带大家来学习C中的设计模式&#xff0c;这篇文章主要带大家学习工厂模式。 一、什么是工厂模式 工厂模式&#xff08;Factory P…

洗涤护理门店小程序DIY制作教程

随着移动互联网的快速发展&#xff0c;小程序成为了各行各业推广和服务的新平台。对于干洗店来说&#xff0c;拥有一个专属的洗护小程序不仅可以提升用户体验&#xff0c;还能增加店铺的曝光度和销售额。那么&#xff0c;如何DIY制作一个干洗店洗护小程序呢&#xff1f; 首先&a…

在Ubuntu上安装和设置RabbitMQ服务器,轻松实现外部远程访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

【最全】MySQL知识点总结

先简单的大致了解一下&#xff0c;学习知识的目的是运用&#xff01;&#xff01;&#xff01; MySQL是什么&#xff1f; 一种关系型数据库管理系统&#xff0c;也就是说这是用来管理数据库的工具。 SQL相关命令 数据库相关 创建数据库&#xff1a;CREATE DATABASE 数据库名; …