微服务——服务异步通讯RabbitMQ
前置文章
消息队列——RabbitMQ基本概念+容器化部署和简单工作模式程序_北岭山脚鼠鼠的博客-CSDN博客
消息队列——rabbitmq的不同工作模式_北岭山脚鼠鼠的博客-CSDN博客
消息队列——spring和springboot整合rabbitmq_北岭山脚鼠鼠的博客-CSDN博客
目录
Work queues 工作队列模式
案例:
在生产者端
在消费者端
结果如下
消费预取限制
发布订阅模型
Fanout Exchange(配置文件实现)
案例
消费者代码
生产者代码
Direct Exchange (注解实现)
案例
消费者代码
生产者代码
Topic Exchange
案例
消费者代码
生产者代码
消息转换器
生产者代码
JSON方式序列化
生产者代码 (jackson)
消费者代码(jackson)
总结
Work queues 工作队列模式
这里用的不是上面第三篇文章里面的定义配置类的形式。
案例:
在生产者端
队列要存在才可以上传。不然代码运行不会报错,但是消息也会不知道发到哪里去。
@Testpublic void testSendMessage2() throws InterruptedException {String queue_Name= "simple.queue";String message="hello 鼠鼠";for(int i=1;i<=50;i++)rabbitTemplate.convertAndSend(queue_Name,message+i);Thread.sleep(20);}
在消费者端
定义了两个消费者监听上面的队列,本来想三个的,但是不知道默认的交换机名字,所以弄了两个。并且根据注解的不同,第一个是可以直接创建一个队列,第二个需要队列已存在才行。
@Component
public class RabbitMQListener {//自动创建队列@RabbitListener(queuesToDeclare=@Queue("simple.queue"))public void ListenerWorkQueue1(Message message) throws InterruptedException {System.out.println("11111"+message.getBody());Thread.sleep(20);}//需要在rabbit_mq上手动创建队列,不然会报错@RabbitListener(queues="simple.queue")public void ListenerWorkQueue2(Message message) throws InterruptedException {System.out.println("22222"+message.getBody());Thread.sleep(200);}//3. 自动创建队列,Exchange 与 Queue绑定
// @RabbitListener(bindings = @QueueBinding(
// value = @Queue("simple.queue"),
// exchange = @Exchange("/") //绑定默认交换机
// ))
// public void ListenerWorkQueue3(Message message) throws InterruptedException {
// System.out.println("33333"+message.getBody());
// Thread.sleep(200);
// }
}
结果如下
两个队列轮流取消息导致反而变慢了。
消费预取限制
要指定队列才有效果。
这里就相当于指定了在simple前缀的队列上每次只能获取一条消息。
运行结果如下,大多数都交给了快的队列执行。
发布订阅模型
Fanout Exchange(配置文件实现)
消息路由到每个绑定的消息队列。
案例
消费者代码
spring读取到这个Bean之后就会向RabbitMq发请求,创建交换机,绑定队列了。
@Configuration
public class FanoutConfig {//itcast.fanout@Beanpublic FanoutExchange fanoutExchange(){return new FanoutExchange("itcast.fanout");}//fanout.queue1@Beanpublic Queue fanoutQueue1(){return new Queue("fannout.queue1");}//绑定队列1到交换机@Beanpublic Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);}//fanout.queue1@Beanpublic Queue fanoutQueue2(){return new Queue("fannout.queue2");}//绑定队列2到交换机@Beanpublic Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);}
}
定义两个监听用的方法
@Component
public class RabbitMQListener {
// @RabbitListener(queues="boot_queue")
// public void ListenerQueue(Message message){
// System.out.println(message);
// }//自动创建队列// @RabbitListener(queuesToDeclare=@Queue("simple.queue"))
// public void ListenerWorkQueue1(Message message) throws InterruptedException {
// System.out.println("11111"+message.getBody()+ LocalDateTime.now());
// Thread.sleep(20);
// }
//
// //需要在rabbit_mq上手动创建队列,不然会报错
// @RabbitListener(queues="simple.queue")
// public void ListenerWorkQueue2(Message message) throws InterruptedException {
// System.out.println("22222"+message.getBody()+ LocalDateTime.now());
// Thread.sleep(200);
// }//3. 自动创建队列,Exchange 与 Queue绑定
// @RabbitListener(bindings = @QueueBinding(
// value = @Queue("simple.queue"),
// exchange = @Exchange("/") //绑定默认交换机
// ))
// public void ListenerWorkQueue3(Message message) throws InterruptedException {
// System.out.println("33333"+message.getBody());
// Thread.sleep(200);
// }@RabbitListener(queuesToDeclare=@Queue("fanout.queue1"))public void ListenerFanoutQueue1(Message message) throws InterruptedException {System.out.println("11111"+message.getBody());}@RabbitListener(queuesToDeclare=@Queue("fanout.queue2"))public void ListenerFanoutQueue2(Message message) throws InterruptedException {System.out.println("22222"+message.getBody());}
}
生产者代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class ProducerTest {//1.注入RabbitTemplate@Autowiredprivate RabbitTemplate rabbitTemplate;// @Test
// public void testSend(){
// rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_NAME,"boot.haha","hello 鼠鼠");
// }// @Test
// public void testSendMessage2() throws InterruptedException {
// String queue_Name= "simple.queue";
// String message="hello 鼠鼠";
//
// for(int i=1;i<=50;i++)
// rabbitTemplate.convertAndSend(queue_Name,message+i);
// Thread.sleep(20);
// }@Testpublic void testSendFanoutExchange(){//交换机名称String exchangeName="itcast.fanout";//消息String message="hello 鼠鼠";//发送消息rabbitTemplate.convertAndSend(exchangeName,"",message);}
}
Direct Exchange (注解实现)
案例
消费者代码
@Component
public class RabbitMQListener { @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name="itcast.direct" , type= ExchangeTypes.DIRECT),key={"red","blue"}))public void listenDirectQueue1(String msg){System.out.println("消费者接收到:"+msg);}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name="itcast.direct" , type= ExchangeTypes.DIRECT),key={"red","yellow"}))public void listenDirectQueue2(String msg){System.out.println("消费者接收到:"+msg);}
}
生产者代码
@Testpublic void testSendDirectExchange(){//交换机名称String exchangeName="itcast.direct";//消息String message="hello 鼠鼠";//发送消息rabbitTemplate.convertAndSend(exchangeName,"blue",message);}
此条代码只有绑定了blue这个key的队列才可以收到。
换成red就是两个队列都可以收到了。
Topic Exchange
案例
消费者代码
@RabbitListener(bindings = @QueueBinding(value=@Queue(name="topic.queue1"),exchange=@Exchange(name="itcast.topic",type = ExchangeTypes.TOPIC),key="japan.#"))public void listenTopicQueue1(String msg){System.out.println("消费者接收到:"+msg);}@RabbitListener(bindings = @QueueBinding(value=@Queue(name="topic.queue2"),exchange=@Exchange(name="itcast.topic",type = ExchangeTypes.TOPIC),key="#.news"))public void listenTopicQueue2(String msg){System.out.println("消费者接收到:"+msg);}
生产者代码
@Testpublic void testSendTopicExchange(){//交换机名称String exchangeName="itcast.topic";//消息String message="北岭山脚鼠鼠横死街头,究竟是人性的沦丧还是道德的....";//发送消息rabbitTemplate.convertAndSend(exchangeName,"japan.news",message);}
两个都符合,所以都能收到。
消息转换器
定义一个队列
@Beanpublic Queue objectQueue(){return new Queue("object.queue");}
生产者代码
@Testpublic void testSendObjectQueue(){//消息Map<String,Object> msg=new HashMap<>();msg.put("name","北岭山脚鼠鼠");msg.put("age","22");//发送消息rabbitTemplate.convertAndSend("object.queue",msg);}
可以看见消息被转换成了一长串字符,content_type写着java的序列化。
效率差,安全性也差。
JSON方式序列化
声明好MessageConveter之后就可以自动覆盖默认序列化方式了。
导入一个核心依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
生产者代码 (jackson)
修改生产者的启动类代码,加上一个Bean
@SpringBootApplication
public class ProducerApplication {public static void main(String[] args) {SpringApplication.run(ProducerApplication.class);}@Beanpublic Jackson2JsonMessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}
}
启动测试类之后可以看见新的消息出现了。
消费者代码(jackson)
然后可以正常接受到消息
如果消费者不使用对应jackson解析的话,代码会报错
总结
推荐使用jackson的方式
相关文章:

微服务——服务异步通讯RabbitMQ
前置文章 消息队列——RabbitMQ基本概念容器化部署和简单工作模式程序_北岭山脚鼠鼠的博客-CSDN博客 消息队列——rabbitmq的不同工作模式_北岭山脚鼠鼠的博客-CSDN博客 消息队列——spring和springboot整合rabbitmq_北岭山脚鼠鼠的博客-CSDN博客 目录 Work queues 工作队列…...
事件冒泡、事件捕获和事件委托
原文合集地址如下,有需要的朋友可以关注 本文地址 合集地址 什么是事件冒泡、事件捕获和事件委托? 事件冒泡(Event Bubbling)、事件捕获(Event Capturing)和事件委托(Event Delegation&…...
WEB 典型安全功能说明
WEB 典型安全功能 认证Authentication 认证是指通过验证用户的身份来确认用户是否有权访问某个系统或资源。在Web安全中,认证是非常重要的一环,它可以防止未经授权的访问,保护用户的数据和系统的安全。 登录 登录是用户认证的常见方式之一…...

SQL编译优化原理
最近在团队的OLAP引擎上做了一些SQL编译优化的工作,整理到了语雀上,也顺便发在博客上了。SQL编译优化理论并不复杂,只需要掌握一些关系代数的基础就比较好理解;比较困难的在于reorder算法部分。 文章目录 基础概念关系代数等价 j…...
qt signal slots lambda
这里用到了qt的版本检测 连接 Combox的currentIndexChanged事件 emit来触发处理的事件 ,进行业务或逻辑处理 这样的写法是lambda表达式的写法,和c#中的 (obj)>{ //todo } 类同 [](int indx){ //todo } #if QT_VERSION > QT_VERSION_CHECK(5,7,0)c…...
Spring【声明式事务】
事务简介 把一组业务当成一个业务来做;要么都成功,要么都失败!事务在项目开发中,十分重要,涉及到数据一致性的问题,需要十分注意!确保完整性和一致性! 事务的ACID原则:…...

【雕爷学编程】MicroPython动手做(17)——掌控板之触摸引脚2
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...

pytorch 中 view 和reshape的区别
在 PyTorch(一个流行的深度学习框架)中, reshape 和 view 都是用于改变张量(tensor)形状的方法,但它们在实现方式和使用上有一些区别。下面是它们之间的主要区别: 实现方式: reshap…...

认识数组指针
文章目录 数组指针的定义数组指针的应用 数组指针的定义 类比 整形数组——存放整形的数组 指针数组——存放指针的数组 整形指针——存放整形地址的指针 数组指针——存放数组地址的指针 深度理解 在之前我们知道:数组名表示首元素地址,但是有…...

SSM面试题-Spring容器的启动流程
解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后,将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…...
Vue 3:玩一下web前端技术(八)
前言 本章内容为VUE基础与相关技术讨论。 上一篇文章地址: Vue 3:玩一下web前端技术(七)_Lion King的博客-CSDN博客 下一篇文章地址: (暂无) 一、基础 官方文档:创建一个 Vue…...

AI绘画Stable Diffusion原理之Autoencoder-Latent
前言 传送门: stable diffusion:Git|论文 stable-diffusion-webui:Git Google Colab Notebook:Git kaggle Notebook:Git 今年AIGC实在是太火了,让人大呼许多职业即将消失,比如既能帮…...
C++核心知识点总结
学习一门新的程序设计语言得到最好方法就是练习编写程序! C基础 变量和基本类型 基本内置类型 定义解释 算术类型 整型:包括字符和布尔类型,bool、char、wchar_t、char16_t、char32_t、short、int、long、long long、 浮点型:…...

echart折线图,调节折线点和y轴的间距(亲测可用)
options代码: options {tooltip: {trigger: axis, //坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。},xAxis: {type: category,//类目轴,适用于离散的类目数据,为该类型时必须通过 data 设置类目数据。…...

Power BI-云端报表定时刷新--ODBC、MySQL、Oracle等其他本地数据源的刷新(二)
ODBC数据源 一些小众的数据源无法直接连接,需要通过微软系统自带的应用“ODBC数据源”连接。 1.首次使用应安装对应数据库的ODBC驱动程序,Mysql的ODBC驱动需要手动安装 2.在web服务中进行数据源的配置 Mysql数据源 1.Powerbi与Gateway第一次连SQL…...

redis 淘汰策略和持久化
文章目录 一、淘汰策略1.1 背景1.2 淘汰策略 二、持久化2.1 AOF日志2.1.1 AOF配置2.1.2 AOF策略2.1.3 AOF缺点2.1.4 AOF Rewrite2.1.5 AOF Rewrite配置2.1.6 AOF Rewrite缺点2.1.7 fork进程时的写时复制2.1.8 大key对持久化的影响 2.2 RDB快照2.2.1 RDB配置2.2.2 RDB缺点 2.3 混…...

Redis学习路线(6)—— Redis的分布式锁
一、分布式锁的模型 (一)悲观锁: 认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行。例如Synchronized、Lock都属于悲观锁。 优点: 简单粗暴缺点: 性能略低 &#x…...

一、创建自己的docker python容器环境;支持新增python包并更新容器;离线打包、加载image
1、创建自己的docker python容器环境 参考:https://blog.csdn.net/weixin_42357472/article/details/118991485 首先写Dockfile,注意不要有txt等后缀 Dockfile # 使用 Python 3.9 镜像作为基础 FROM python:3.9# 设置工作目录 WORKDIR /app# 复制当前…...

【Git】git企业开发命令整理,以及注意点
1.git企业开发过程 业务的分支大概有以下几个: master:代码随时可能上线 develop:代码最新 feature/xxx:实际业务开发分支 release/xxx:预发布分支 fix:修复bug分支 过程大概是这样的: 首…...

使用Django自带的后台管理系统进行数据库管理的实例
Django自带的后台管理系统主要用来对数据库进行操作和管理。它是Django框架的一个强大功能,可以让你快速创建一个管理界面,用于管理你的应用程序的数据模型。 使用Django后台管理系统,你可以轻松地进行以下操作: 数据库管理&…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...