RabbitMQ消息队列
简介
MQ(message queue),从字面意思上看就个 FIFO 先入先出的队列,只不过队列中存放的内容是 message 而已,它是一种具有接收数据、存储数据、发送数据等功能的技术服务。
作用:流量削峰、应用解耦、异步处理。
生产者将消息发送到消息队列中,消息队列负责转发消息给消费者,消费者在处理完消息后会对消息队列进行应答,消息队列收到应答信息会将相应的消息进行丢弃。
批量应答会导致高并发时消息的丢失,所以尽力以channel.ack()进行手动应答。
docker安装
- 拉取镜像并后台运行
docker run -id --name=rabbitmq -v rabbitmq-home:/var/lib/rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=yi -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq
需要将RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS改成自己的用户名、密码。
- 开启manager插件,可以在网页进行管理。
docker exec -it 容器id /bin/bash #这里可以用docker ps 查询刚刚开启的容器id#进入容器后输入,开启rabbitmq-plugins enable rabbitmq_management
可以登录 http://服务器IP:15672 访问web管理界面,访问成功则代表开启成功。
JAVA环境搭建
jar包:
<dependencies><dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.8.0</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.25</version></dependency></dependencies>
Helloworld实例
生产者
public static void main(String[] args) throws IOException, TimeoutException {//创建连接工厂ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("127.0.0.1");connectionFactory.setUsername("yi");connectionFactory.setPassword("123456");//获取连接Connection connection = connectionFactory.newConnection();//获取信道,一个连接中有多个信道Channel channel = connection.createChannel();//声明一个队列 String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> argumentsAMQP.Queue.DeclareOk declareOk = channel.queueDeclare(QUEUE_NAME,false,false,false,null);String message="hello world";//(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)channel.basicPublish("",QUEUE_NAME,null,message.getBytes());System.out.println("发送成功");}
消费者
public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost("127.0.0.1");connectionFactory.setUsername("yi");connectionFactory.setPassword("123456");Connection connection = connectionFactory.newConnection();Channel channel = connection.createChannel();DeliverCallback deliverCallback=(consumerTag,message)->{System.out.println(new String(message.getBody()));};CancelCallback cancelCallback=(String var1)->{System.out.println("消息消费被中断");};channel.basicConsume(QUEUE_NAME,true,deliverCallback,cancelCallback);}
工作队列(任务队列)
RabbitMQ默认为工作队列模式,消费者C1,C2为竞争关系,接收到的消息将轮询发送给C1,C2处理,即C1一条C2一条依次循环。
手动应答ack
因为自动应答不会考虑消息是否处理成功,所以可能会导致消息丢失,需要在代码中将自动应答改为手动应答。批量应答在高并发的时候也容易丢失消息,也应该关闭。
生产者的代码无需修改。
消费者:
public static void main(String[] args) throws IOException, TimeoutException {Channel channel = RabbitMQUtils.getChannel();System.out.println("work2 waiting:");DeliverCallback deliverCallback= (String s, Delivery delivery)->{System.out.println(new String(delivery.getBody()));// do something//手动回复ack,false为关闭批量应答channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);};CancelCallback cancelCallback=(s)->{System.out.println("消息被打断");};//false表示不自动应答ackchannel.basicConsume(QUEUE_NAME,false,deliverCallback,cancelCallback);}
不公平分发
会存在有些线程能力差耗时长,有些能力强耗时短的情况,不公平分发将实现能者多劳。
设立channel的basicQos即可实现不公平分发, basicQos的数值意味着channel的最大存储上限,channel为1时,消费者最多同时缓存一条待处理消息。
channel.basicQos(1);
发布确认
在开启队列持久化、消息持久化后,RabbitMQ服务器仍然可能在将消息存储在磁盘前宕机,需要发布确认才能保证消息不丢失,即RabbitMQ在存储磁盘成功后,发送确认给生产者。
单个发布确认
每条消息存储在磁盘后进行发布确认,只有发送者在接收到消费者对应的发布确认消息后才会给此消费者发送下一条消息。
public static void publicMsgIndividual()throws Exception{Channel channel = RabbitMQUtils.getChannel();String QUEUE_NAME = UUID.randomUUID().toString();//开启持久化channel.queueDeclare(QUEUE_NAME,true,false,false,null);channel.confirmSelect();//开启发布确认long begin = System.currentTimeMillis();for (int i = 0; i < 1000; i++) {channel.basicPublish("",QUEUE_NAME,null, new String(i+" ").getBytes()); boolean flag = channel.waitForConfirms(); //等待发布确认if(flag){System.out.println("消息发送成功");}}long end = System.currentTimeMillis();System.out.println("发布1000条耗时:"+(end-begin)+"ms");}
批量发布确认
每发送100条消息进行一次发布确认。速度快,但是不知道具体是哪一条消息发送失败了。
public static void publicMsgIndividual()throws Exception{Channel channel = RabbitMQUtils.getChannel();String QUEUE_NAME = UUID.randomUUID().toString();//开启持久化channel.queueDeclare(QUEUE_NAME,true,false,false,null);channel.confirmSelect();//开启发布确认long begin = System.currentTimeMillis();for (int i = 0; i < 1000; i++) {channel.basicPublish("",QUEUE_NAME,null, new String(i+" ").getBytes());if(i%100==0){boolean flag = channel.waitForConfirms(); //等待发布确认if(flag){System.out.println("消息发送成功");}}}long end = System.currentTimeMillis();System.out.println("发布1000条耗时:"+(end-begin)+"ms");}
异步发布确认
推荐使用,需要加入确认发布监听器confirmListener,并且记录序列号与消息的关联(ConcurrentSkipListMap)。
public static void publicMsgAsync()throws Exception{Channel channel = RabbitMQUtils.getChannel();String QUEUE_NAME = UUID.randomUUID().toString();//开启持久化channel.queueDeclare(QUEUE_NAME,true,false,false,null);channel.confirmSelect();//开启发布确认// 将序列号与信息相关联,ConcurrentSkipListMap concurrentSkipListMap = new ConcurrentSkipListMap<Long,String>();//加入确认监听器channel.addConfirmListener(new ConfirmListener() {@Overridepublic void handleAck(long msgTag, boolean multiply) throws IOException {System.out.println("消息发送成功:"+msgTag);if(multiply) { //如果是批量确认,批量删除//headMap返回小于msgTag的map视图ConcurrentNavigableMap concurrentNavigableMap = concurrentSkipListMap.headMap(msgTag);//清理已经标记的MapconcurrentNavigableMap.clear();}else {concurrentSkipListMap.remove(msgTag);}}@Overridepublic void handleNack(long msgTag, boolean multiply) throws IOException {System.out.println("未确认的消息:"+concurrentSkipListMap.get(msgTag));}});long begin = System.currentTimeMillis();for (int i = 0; i < 1000; i++) {channel.basicPublish("",QUEUE_NAME,null, new String(i+" ").getBytes());//记录发送的信息与其序列号concurrentSkipListMap.put(channel.getNextPublishSeqNo(),new String(i+" "));}long end = System.currentTimeMillis();System.out.println("发布1000条耗时:"+(end-begin)+"ms");}
发布/订阅模式(fanout交换机)
首先要弄明白交换机和队列的关系,交换机负责信息的接收,通过不同的RountingKey将消息转发到不同的队列,每个队列上的接收者都是竞争关系(即队列上的消息只会被处理一次),那么当一个交换机对应多个队列时,每个队列仅有一个消费者,这个时候即发布/订阅模式,消息会被每个消费者接收。
生产者代码:向交换机中发送消息
public static final String EXCHANGE_NAME="logs";public static void main(String[] args) throws IOException, TimeoutException {Channel channel = RabbitMQUtils.getChannel();Scanner scanner = new Scanner(System.in);while (scanner.hasNext()){String next = scanner.next();channel.basicPublish(EXCHANGE_NAME,"", null,next.getBytes());}}
消费者代码:声明匿名队列,将队列绑定到交换机上,不同的消费者用相同的RountingKey,以便同时接收到消息。
public static final String EXCHANGE_NAME="logs";public static void main(String[] args) throws IOException, TimeoutException {Channel channel = RabbitMQUtils.getChannel();channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT); //FANOUT煽出,就是发布订阅模式String queue = channel.queueDeclare().getQueue(); //声明匿名队列channel.queueBind(queue,EXCHANGE_NAME,""); //将队列绑定到交换机上,RountingKey为“”DeliverCallback deliverCallback=(consumerTag,message)->{System.out.println("接收到消息:"+new String(message.getBody()));};channel.basicConsume(queue,true,deliverCallback, (consumerTag)->{});}
Direct交换机
与fanout模式相比,不同的队列有不同的Rounting key,通过Rounting Key能够直接向指定队列发送消息。
Topic交换机
rountingKey作为匹配串,发送消息时,匹配上的则能进行发送。
routingKey必须是单词列表,用.隔开。如aa.bb.cc
*可以代表一个单词 ,#可以代表若干个单词
比如向rountingKey为aa.orange.rabbit发送消息,Q1和Q2都能接收到消息,而向aa.orange.bb发送消息则只有Q1能够接收到消息。
当队列的rountingKey绑定的#,则相当于fanout煽出交换机。
当队列的rountingKey绑定不带#*时,相当于direct交换机。
死信队列
在队列中1消息超时、2无法处理、3队列已满时,消息会被送入死信队列。
相关文章:

RabbitMQ消息队列
简介 MQ(message queue),从字面意思上看就个 FIFO 先入先出的队列,只不过队列中存放的内容是 message 而已,它是一种具有接收数据、存储数据、发送数据等功能的技术服务。 作用:流量削峰、应用解耦、异步处理。 生产者将消息发送…...

ModBus电表与RS485电表有哪些区别?
在能源计量领域,ModBus电表和RS485电表是两种常见的设备,它们都具有监测和记录电能数据的功能。然而,它们之间存在一些区别,比如通信协议、连接方式、数据格式等等参数的区别有哪些? ModBus电表和RS485电表都是用于电能…...

vue项目运行时,报错:ValidationError: webpack Dev Server Invalid Options
在运行vue项目中,遇到报错:ValidationError: webpack Dev Server Invalid Options,如下图截图: 主要由于vue.config.js配置文件错误导致的,具体定位到proxy配置代理不能为空,导致运行项目报错,需…...
书摘:C 嵌入式系统设计模式 02
本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。 本系列描述我对书中内容的理解。 结构化编程将软件组织成两个截然不同的…...

排序算法基本原理及实现1
📑打牌 : da pai ge的个人主页 🌤️个人专栏 : da pai ge的博客专栏 ☁️宝剑锋从磨砺出,梅花香自苦寒来 📑插入排序 Ǵ…...

Unity 轨道展示系统(DollyMotion)
DollyMotion 🍱功能展示🥙使用💡设置路径点💡触发点位切换💡动态更新路径点💡事件触发💡设置路径💡设置移动方案固定速度方向最近路径方向 💡设置移动速度曲线 传送门 &a…...

优维低代码实践:搜索功能
优维低代码技术专栏,是一个全新的、技术为主的专栏,由优维技术委员会成员执笔,基于优维7年低代码技术研发及运维成果,主要介绍低代码相关的技术原理及架构逻辑,目的是给广大运维人提供一个技术交流与学习的平台。 优维…...

C# ReadOnlyRef Out
C# ReadOnly ReadOnly先看两种情况1.值类型2.引用类型 结论 Ref Out ReadOnly官方文档 ReadOnly 先看两种情况 1.值类型 当数据是值类型时,标记为Readonly时,如果再次设置值,会提示报错,无法分配到只读字段 public class A {pri…...

linux 服务 下 redis 安装和 启动
官网下载 https://redis.io/download/ 安装步骤: 1.安装redis 所需要的依赖 yum install -y gcc tcl2.上传安装包并解压,下载安装包,上传到/usr/local/src目录,解压 tar -zxvf redis-7.2.3.tat.gz进入安装目录,运行…...
ECharts与Excel的结合实战
引言:本文是一篇ECharts和Excel实战的记录。将Excel与ECharts产生火花,从Excel读取数据然后在ECharts上展示。 1.柱状图前端代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title…...
UDP的特点及应用场景
目录 UDP特点 应用场景 总结 User Datagram Protocol(UDP,用户数据报协议)是互联网协议套件中的一种传输层协议。与TCP不同,UDP是一种无连接的、不可靠的协议。 UDP特点 要知道UDP可以用来做什么,首先我们要知道它…...

Python开发——工具篇 Pycharm的相关配置,Python相关操作 持续更新
前言 本篇博客是python开发的工具篇相关,介绍pycharm的使用和相关配置,收录python的相关操作,比如如何启动jupyter。 目录 前言引出Pycharmpycharm如何不同等级日志显示不同颜色设置不同pycharm的python环境 Python操作如何启动Jupyter 总结…...

【深度学习】卷积神经网络结构组成与解释
卷积神经网络是以卷积层为主的深度网路结构,网络结构包括有卷积层、激活层、BN层、池化层、FC层、损失层等。卷积操作是对图像和滤波矩阵做内积(元素相乘再求和)的操作。 1. 卷积层 常见的卷积操作如下: 卷积操作解释图解标准卷…...

从源码解析Containerd容器启动流程
从源码解析Containerd容器启动流程 本文从源码的角度分析containerd容器启动流程以及相关功能的实现。 本篇containerd版本为v1.7.9。 更多文章访问 https://www.cyisme.top 本文从ctr run命令出发,分析containerd的容器启动流程。 ctr命令 查看文件cmd/ctr/comman…...

引迈-JNPF低代码项目技术栈介绍
从 2014 开始研发低代码前端渲染,到 2018 年开始研发后端低代码数据模型,发布了JNPF开发平台。 谨以此文针对 JNPF-JAVA-Cloud微服务 进行相关技术栈展示: 1. 项目前后端分离 前端采用Vue.js,这是一种流行的前端JavaScript框架&a…...

如何处理枚举类型(下)
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 上一篇我们通过编写MyB…...

wsj0数据集原始文件.wv1.wv2转换成wav文件
文章目录 准备一、获取WSJO数据集二、安装sph2pipe三、转换代码四、结果展示 最近做语音分离实验需要用到wsj0-2mix数据集,但是从李宏毅语音分离教程里面获取的wsj0-2mix只有一部分。从网上获取到了完整的WSJO数据集后,由于原始的语音文件后缀是wv1或…...

Flask Session 登录认证模块
Flask 框架提供了强大的 Session 模块组件,为 Web 应用实现用户注册与登录系统提供了方便的机制。结合 Flask-WTF 表单组件,我们能够轻松地设计出用户友好且具备美观界面的注册和登录页面,使这一功能能够直接应用到我们的项目中。本文将深入探…...

【运维】hive 高可用详解: Hive MetaStore HA、hive server HA原理详解;hive高可用实现
文章目录 一. hive高可用原理说明1. Hive MetaStore HA2. hive server HA 二. hive高可用实现1. 配置2. beeline链接测试3. zookeeper相关操作 一. hive高可用原理说明 1. Hive MetaStore HA Hive元数据存储在MetaStore中,包括表的定义、分区、表的属性等信息。 hi…...

C#开发的OpenRA游戏之属性SelectionDecorations(13)
C#开发的OpenRA游戏之属性SelectionDecorations(13) 在前面分析SelectionDecorations属性类时,会发现它有下面这个属性: public class SelectionDecorations : SelectionDecorationsBase, IRender { readonly Interactable interactable; 它是定义了一个Interactabl…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...