RabbitMQ-高级
RabbitMQ-高级
文章目录
- RabbitMQ-高级
- 前言:消息可靠性问题
- 1.生产者可靠性
- 1.生产者重连
- 2.生产者确认机制
- 3.生产者代码实现原理
- 2.MQ的可靠性
- 1.数据持久化
- 2.LazyQueue
- 3.消费者可靠性
- 1.消费者确认机制
- 1.确认机制
- 2.确认功能
- 2.失败重试机制
- 1.开启失败重试机制
- 2.多次失败处理
- 3.业务幂等性
- 4.延迟消息
- 1.理解延迟消息
- 2.延迟消息的实现
- 1.死信交换机
- 2.延迟消息插件
前言:消息可靠性问题
如图,在实现业务中可能会出现以下几个问题:
- 支付服务向MQ发送消息时网络故障,导致消息消息丢失
- MQ还没有来得及发送至交易服务,自己宕机导致消息丢失
- 交易服务执行时抛出异常或者宕机
这三个任意一部分出现问题都会导致业务的执行失败,因此我们来一起学习MQ如何保证消息可靠性。
1.生产者可靠性
1.生产者重连
有的时候由于网络波动,可能会出现客户端连接MQ失败的情况。通过配置我们可以开启连接失败后的重连机制:
spring:rabbitmq:connection-timeout: ls # 设置MQ的连接超时时间template:retry:enabled: true # 开启超时重试机制initial-interval: 1000ms # 失败后的初始等待时间multiplier: l # 失败后下次的等待时长倍数,下次等待时长 = initial-interval * multipliermax-atempts: 3 # 最大重试次数
注意:(客户端连接的重试,不是消息发送的重试)
当网络不稳定的时候,利用重试机制可以有效提高消息发送的成功率。不过SpringAMQ提供的重试机制是阻塞式的重试,也就是说多次重试等待的过程中,当前线程是被阻塞的,会影响业务性能。
如果对于业务性能有要求,建议禁用重试机制。如果一定要使用,请合理配置等待时长和重试次数,当然也可以考虑使用异步线程来执行发送消息的代码。
2.生产者确认机制
RabbitMq实现了Publisher Confirm和Publisher Return两种确认机制。开启确认机制后,在MQ成功收到消息后会返回确认消息给生产者。返回的结果有以下几种:
- 消息投递到了MQ,但是路由失败(一般会是代码或者路由配置的问题)。此时会通过Publisher Return返回路由异常原因,然后返回ACK,告知投递成功。
- 临时消息投递到了MQ,并且成功进入队列,返回ACK,告知投递成功
- 持久消息投递到了MQ,并且成功进入队列和持久化,返回ACK,告知投递成功
- 其他情况都会返回NACK,告知投递失败
3.生产者代码实现原理
使用SpringAMQP实现生产者确认
-
在publisher这个微服务的application.yml中添加配置:
spring:rabbitmq:publisher-confirm-type: correlated # 开启publisher confirm机制,并设置confirm类型publisher-returns: true # 开启publisher return机制 #配置说明: #这里publisher-confirm-type有三种模式可选:#none:关闭confirm机制#simple:同步阻塞等待MQ的回执消息#correlated:MQ异步回调方式返回回执消息
-
每个RabbitTemplate只能配置一个ReturnCallback,因此需要在项目启动过程中配置:
@S1f4j
@Configuration
public class CommonConfig implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{// 获取RabbitTemplateRabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);// 设置ReturnCallbackrabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {@Overridepublic void returnedMessage(ReturnedMessage returnedMessage) {log.info("收到消息的ReturnBack: exchange:{}, route:{}, replyCode:{}, replyText:{}",returnedMessage.getExchange(),returnedMessage.getRoutingKey(),returnedMessage.getReplyCode(),returnedMessage.getReplyText());}});
}}
关于ApplicationContextAware :
-
定义
ApplicationContextAware
是 Spring 框架提供的一个接口,允许 Bean 感知并获取 Spring 容器的引用(即ApplicationContext
)。当一个类实现该接口后,Spring 会在初始化该 Bean 时自动调用setApplicationContext()
方法,并传入当前的ApplicationContext
对象。 -
作用
获取 Spring 容器(
ApplicationContext
),用于动态管理 Bean、读取配置、发布事件等。在非依赖注入场景下访问 Spring 功能,例如在工具类或配置类中手动获取 Bean。
-
使用场景
动态获取 Bean(如运行时根据条件加载不同的组件)。
配置全局回调(如示例中的
RabbitTemplate
设置ReturnCallback
)。框架扩展(如自定义 Starter 需要与 Spring 容器交互)
3.发送消息,指定消息Id,消息ConfirmCallBack(每次发消息时指定)
@Test
void testPublisherConfirm() throws InterruptedException {// 1. 创建CorrelationDataCorrelationData cd = new CorrelationData();// 2. 给Future添加ConfirmCallbackcd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {@Overridepublic void onFailure(Throwable ex) {// 2.1. Future发生异常时的处理逻辑,基本不会触发log.error("Handle message ack fail", ex);}@Overridepublic void onSuccess(CorrelationData.Confirm result) {// 2.2. Future接收到回执的处理逻辑,参数中的result就是回执内容if(result.isAck()){ // result.IsAck(), boolean类型, true代表ack回执, false 代表 nack回执log.debug("发送消息成功,收到 ack!");}else{ // result.getReason(), String类型, 返回nack时的异常描述log.error("发送消息失败,收到 nack, reason : {}", result.getReason());}}});// 3. 发送消息rabbitTemplate.convertAndSend("ExchangeName", "RoutingKey", "hello", cd);
}
关于CorrelationData:
- 唯一标识消息
CorrelationData
通常包含一个唯一的ID
(如correlationId
),用于标识某条消息,以便在收到 ACK/NACK 回执时能正确匹配到对应的消息。- 如果不手动设置
ID
,RabbitMQ 会自动生成一个。
- 接收消息确认结果
- 通过
cd.getFuture()
可以获取一个ListenableFuture
,用于异步监听该消息的 ACK(成功) 或 NACK(失败) 回执。 - 示例代码中通过
addCallback()
方法注册回调,处理消息的确认结果。
- 通过
- 与
rabbitTemplate
配合使用- 在发送消息时(
convertAndSend
),将CorrelationData
传入,RabbitMQ 会在 Broker 确认消息后,通过该对象返回结果
- 在发送消息时(
2.MQ的可靠性
在默认情况下,RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟。这样会导致两个问题:
- 一旦MQ宕机,内存中的消息会丢失
- 内存空间有限,当消费者故障或处理过慢时,会导致消息积压,引发MQ阻塞
如图当MQ的消息堆积时,MQ会执行PageOut,将老的消息落到磁盘上,给内存腾出空间,而这个过程MQ是阻塞执行的,此时来新的消息就可能无法执行,严重影响效率。
1.数据持久化
RabbitMQ实现数据持久化的3个方面:
-
交换机持久化(默认临时,在java代码中实现则是默认持久化,队列一样)
-
队列持久化
-
消息持久化
Delivery mode为2时则为持久模式
这里给出消息持久和非持久代码,大家可以尝试测试MQ的运行过程:
@Testvoid testPageOut(){Message message = MessageBuilder.withBody(("Hello,world!").getBytes())//持久化.setDeliveryMode(MessageDeliveryMode.PERSISTENT).build();//非持久化//.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT).build();for (int i=0;i<1000000;i++){rabbitTemplate.convertAndSend("study.direct","blue",message);}}
如图为开启了生产者确认机制下消息非持久化,会发现大约三十秒左右只发送了十分之一。(看In memory)
此时我们关闭后再次执行会发现消息处理快很多,此时出现Paged Out,图中折线降为0处即执行Paged Out出现阻塞。
下图为消息持久化,会发现并未执行Paged Out,Persistent表示持久化到磁盘中,每当In memory到达阈值会删除一些信息,此时折线图的暂时下降一些(效率暂时降低)。
2.LazyQueue
从RabbitMQ的3.6.0版本开始,就增加了Lazy Queue的概念,也就是惰性队列。
惰性队列的特征如下:
- 接收到消息后直接存入磁盘而非内存(内存中只保留最近的消息,默认2048条)
- 消费者要消费消息时才会从磁盘中读取并加载到内存
- 支持数百万条的消息存储
在3.12版本后,所有队列都是Lazy Queue模式,无法更改。
-
要设置一个队列为惰性队列,只需要在声明队列时,制定x-queue-mode属性为lazy即可:(3.12后的默认为lazy)
-
在java代码中
基于注解
如图为我们向lazy队列发送一百万条数据:
会发现所有消息直接写进Paged Out,且几乎一直在峰值,执行时间也只有19s
相比消息持久化快了很多(虽然是写入磁盘,但底层对IO有特殊处理)。
3.消费者可靠性
1.消费者确认机制
1.确认机制
为了确认消费者是否成功处理消息,RabbitMQ提供了消费者确认机制(Consumer Acknowledgement)。当消费者处理消息结束后,应该向RabbitMQ发送一个回执,告知RabbitMQ自己消息处理状态。
回执有三种可选值:
- ack:
成功处理
消息,RabbitMQ从队列中删除该消息
- nack: 消息
处理失败
,RabbitMQ需要再次投递消息
- reject:
消息处理失败并拒绝该消息
,RabbitMQ**从队列中删除
**该消息
2.确认功能
SpringAMQP实现了消息确认功能。并允许我们通过配置文件选择ACK处理方式。
有以下三种方式:
-
none:**不处理。**即消息发送给消费者后立刻ack,消息会立刻从MQ删除。非常不安全,不建议使用
-
manual:**手动模式。**需要自己在业务代码中调用api,发送ack或reject,存在业务入侵,但更灵活
-
auto:自动模式。SpringAMQP利用AOP对我们的消息处理逻辑做了环绕增强,当业务正常执行时则自动返回ack。
业务异常时,根据异常判断返回不同结果:
-
如果是业务异常,会自动返回nack
-
如果是消息处理或检验异常,会自动返回reject
spring:rabbitmq:listener:simple:prefetch: 1acknowledge-mode: none #关闭ack;manual,手动ack;auto,自动ack
-
大家可以在编写代码测试效果,这里不做演示。
2.失败重试机制
1.开启失败重试机制
当消费者出现异常后,消息会不断requeue(重新入队)到队列,再重新发送给消费者,然后再次异常,再次requeue,无限循环,导致mq的消息处理频升,带来不必要的压力。
我们可以利用Spring的retry机制,在消费者出现异常时利用本地重试,而不是无限制的requeue到mq队列:
spring: rabbitmq: listener: simple: prefetch: 1acknowledge-mode: autoretry: enabled: true # 开启消费者失败重试 initial-interval: 1000ms # 初始的失败等待时长为1秒 multiplier: 1 # 下次失败的等待时长倍数,下次等待时长 = multiplier * last-interval max-attempts: 3 # 最大重试次数 stateless: true # true无状态; false有状态。如果业务中包含事务,这里改为false #如果消息处理逻辑不涉及事务(如纯计算、查询等),用 stateless: true(默认值)。#如果消息处理包含事务(如订单支付等),需设为 stateless: false,否则重试时事务可能失效
2.多次失败处理
在开启重试模式后,重试次数耗尽,如果消息依然失败,则需要有 MessageRecoverer
接口来处理,它包含三种不同的实现:
-
RejectAndDontRequeueRecoverer:重试耗尽后,直接
reject
,丢弃消息。默认就是这种方式。 -
ImmediateRequeueMessageRecoverer:重试耗尽后,返回
nack
,消息重新入队。 -
RepublishMessageRecoverer:重试耗尽后,将失败消息投递到指定的交换机,后续人工介入。
这里我们演示一下第三种方式:
-
将失败处理策略改为RepublishMessageRecoverer
a. 首先,定义接收失败消息的交换机,队列及其绑定关系
b. 然后,定义RepublishMessageRecoverer@Configurationpublic class DirectConfiguration {@Beanpublic DirectExchange directExchange() {return new DirectExchange("error.exchange");}@Beanpublic Queue errorQueue() {return new Queue("error.queue");}@Beanpublic Binding errorBinding(Queue errorQueue,DirectExchange directExchange){return BindingBuilder.bind(errorQueue).to(directExchange).with("error");}@Beanpublic MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate) {return new RepublishMessageRecoverer(rabbitTemplate, "error.exchange", "error");}}
-
启动消费者并使用生产者发送消息
//消费者@RabbitListener(queues = "simple.queue")public void listener2(String msg){log.info("我是超人收到消息:{}",msg);throw new RuntimeException("故意的");} //----------------------------------------------------------------- //生产者@Testvoid testSendMessage2Queue(){String queueName="simple.queue";String msg="Hello,world!";rabbitTemplate.convertAndSend(queueName,msg);}
-
运行结果
error.queue收到的消息
3.业务幂等性
幂等是一个数学概念,用函数表达式来描述是这样的:f(x)=f(f(x))
。在程序开发中,则是只同一个业务,执行一次或多次对业务状态的影响是一致的。
因此为了保证业务幂等性我们应该怎么做呢?
这里给出个解决方案:
-
唯一消息Id
- 每一条消息都生成一个唯一的Id,与消息一起投递给消费者。
- 消费者接收到消息后处理自己的业务,业务处理成功后将Id保存到数据库。
- 如果下次又收到相同的消息,去数据库查询是都存在,存在则为重复消息并放弃处理。
@Beanpublic MessageConverter jackaonMessageConvert(){Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();jjmc.setCreateMessageIds(true);return jjmc;} // jjmc.setCreateMessageIds(true);这个方法会给转化的消息加入一个UUID确保Id唯一
-
业务判断
结合业务逻辑,基于业务本身做判断,以修改订单状态为例:我们需要在支付后修改订单状态为已支付,应该在修改订单状态前先查询订单状态,判断状态是否为未支付。只有未支付订单才需要修改,其他状态不做处理:
根据本节学习内容回答问题:
- 如何保证支付服务与交易服务之间的订单状态一致性?
- 首先,支付服务会正在用户支付成功以后利用MQ消息通知交易服务,完成订单状态同步。
- 其次,为了保证MQ消息的可靠性,我们采用了生产者确认机制、消费者确认、消费者失败重试等策略,确保消息投递和处理的可靠性。同时也开启了MQ的持久化,避免因服务有机导致消息丢失。
- 最后,我们还在交易服务更新订单状态时做了业务量等判断,避免因消息重复消费导致订单状态异常。
- 如果交易服务消息处理失败,有没有什么兜底方案?
- 我们可以在交易服务设置定时任务(主动方案,可以想象为高考结束学校(MQ)一直不通知查分(不发送订单信息,可能发送失败),我们自己查(定时任务)),定期查询订单支付状态。这样即便MQ通知失败,还可以利用定时任务作为兜底方案,确保订单支付状态的最终一致性。
4.延迟消息
1.理解延迟消息
延迟消息:生产者发送消息时指定一个时间,消费者不会立刻收到消息,而是在指定时间之后才收到消息。
延时任务:设置在一定时间之后才执行的任务。
2.延迟消息的实现
1.死信交换机
什么是死信交换机
?
当一个队列中的消息满足下列情况之一时,就会成为死信(dead letter):
- 消费者使用
basic.reject
或basic.nack
声明消费失败,并且消息的requeue
参数设置为false
- 消息是一个过期消息(达到了队列或消息本身设置的过期时间),超时无人消费
- 要投递的队列消息堆积满了,最早的消息可能成为死信
如果队列通过dead-letter-exchange
属性制定了一个交换机,那么该队列中的死信就会投递到这个交换机中。这个交换机成为死信交换机(Dead Letter Exchange,简称DLX)。
如图给simple.queue
队列通过属性绑定了dlx.direct交换机
(称作死信交换机,与普通交换机无异),当发布一个过期时间为30s的消息进入队列后,没有消费者消费导致消息过期,此时消息被被转发至死信交换机,最终被消费者消费,利用死信机制实现了延迟消息发送。
我们来简单实现一下:
-
创建两组交换机和队列(图中的两组)并进行关系和属性绑定(这里不做演示自行操作)
-
编写生产者与消费者代码,并设置超时时间
//生产者 @Test void testSendTTLMessage(){ String exchangeName="simple.direct"; String msg="死信"; rabbitTemplate.convertAndSend(exchangeName, "dlx", msg, new MessagePostProcessor(){@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setExpiration("10000");//10sreturn message;}});log.info("发送成功!"); }
//消费者 @RabbitListener(queues = "dlx.queue") public void listenerDlx(String msg) {log.info("我是超人,收到死信消息:{}",msg); }
-
消费者查看消息到达时间
-
发送时间
-
消费者收到时间
-
2.延迟消息插件
RabbitMQ官方推出的一个原生支持延迟消息功能的插件。该插件的原理是设计了一种支持延迟消息功能的交换机,当消息投递到交换机后可以暂存一定时间,到期后再投递到队列。
插件需要自己安装,具体安装方式自行学习。
在java代码中实现发送并监听延迟队列的消息:
//消费者
@RabbitListener(bindings = @QueueBinding(value=@Queue(name="delay.queue",durable ="true"),exchange = @Exchange(name ="delay.direct",delayed = "true"),key ="delay"))public void listenerDelay(String msg)
{log.info("收到delay.queue的延迟消息:{}"+msg);
}
//--------------------------------------------
//生产者
@Test
void testSendDelayMessage()
{String exchangeName="delay.direct";String msg="延迟999999ms+";rabbitTemplate.convertAndSend(exchangeName, "delay", msg, new MessagePostProcessor(){@Overridepublic Message postProcessMessage(Message message) throws AmqpException{message.getMessageProperties().setDelay(5000);//延迟5sreturn message;}});log.info("延迟消息发送成功!");
}
发送结果:
-
生产者发送消息
-
消费者5s后收到消息
如上我们推荐实现延迟消息时使用插件实现,当然所有的定时功能都是有性能损耗的(redis除外),MQ和Spring内部在程序内部维护一个时钟,始终每隔一秒会向前跳一次(精度高的可能毫秒甚至纳秒级跳一次),每定一个定时任务,都需要维护自己的时钟,时钟的运行就需要cpu不断计算,因此定时任务是一种cpu密集型任务,定时任务越多,cpu消耗越大,导致cpu压力增大,所以什么时候去使用它取决于业务的具体情况。
本文系统讲解了RabbitMQ高可靠方案,涵盖生产者确认、持久化机制、消费者重试策略及幂等性保障,同时解析了延迟消息的两种实现方式(死信交换机和插件)。通过配置重试、ACK机制和Lazy Queue优化性能与可靠性,结合业务场景设计兜底方案,确保消息最终一致性。学习后深刻体会到消息队列在分布式系统中保障数据安全与高效传输的核心价值。
相关文章:
RabbitMQ-高级
RabbitMQ-高级 文章目录 RabbitMQ-高级前言:消息可靠性问题1.生产者可靠性1.生产者重连2.生产者确认机制3.生产者代码实现原理 2.MQ的可靠性1.数据持久化2.LazyQueue 3.消费者可靠性1.消费者确认机制1.确认机制2.确认功能 2.失败重试机制1.开启失败重试机制2.多次失…...
深入解析Spring Boot与Kafka集成:构建高效消息驱动微服务
深入解析Spring Boot与Kafka集成:构建高效消息驱动微服务 引言 在现代微服务架构中,消息队列扮演着至关重要的角色,而Apache Kafka凭借其高吞吐量、低延迟和可扩展性,成为了许多企业的首选。本文将详细介绍如何在Spring Boot应用…...
Unreal Engine: Windows 下打包 AirSim项目 为 Linux 平台项目
环境: Windows: win10, UE4.27, Visual Studio 2022 Community.Linux: 22.04 windows环境安装教程: 链接遇到的问题(问题:解决方案) 点击Linux打包按钮,跳转至网页而不是执行打包流程:用VS打开项…...
【图像大模型】FLUX.1-dev:深度解析与实战指南
FLUX.1-dev:深度解析与实战指南 一、引言二、模型架构与技术原理(一)模型架构(二)Rectified Flow 技术(三)指导蒸馏(Guidance Distillation) 三、项目运行方式与执行步骤…...
mariadb 升级 (通过yum)
* 注意下 服务名, 有的服务器上是mysql,有的叫mariadb,mysqld的 #停止 systemctl stop mysql #修改源 vi /etc/yum.repos.d/MariaDB.repo baseurl http://yum.mariadb.org/11.4/centos7-amd64 #卸载 yum remove mysql #安装 yum install MariaDB-server galera-4 MariaDB-…...
Flink 非确定有限自动机NFA
Flink 是一个用于状态化计算的分布式流处理框架,而非确定有限自动机(NFA, Non-deterministic Finite Automaton)是一种在计算机科学中广泛使用的抽象计算模型,常用于正则表达式匹配、模式识别等领域。 Apache Flink 提供了对 NFA…...
Profinet转Ethernet IP主站网关:点燃氢醌生产线的智慧之光!
案例分享:转角指示器和Profinet转EthernetIP网关的应用 在现代工业自动化中,设备和系统之间的高效通信至关重要。最近,我们在某大型化工企业的生产线上实施了一个项目,旨在通过先进的设备和通信技术提高生产效率和安全性。该项目…...
动态IP技术在跨境电商中的创新应用与战略价值解析
在全球化4.0时代,跨境电商正经历从"流量红利"向"技术红利"的深度转型。动态IP技术作为网络基础设施的关键组件,正在重塑跨境贸易的运营逻辑。本文将从技术架构、应用场景、创新实践三个维度,揭示动态IP如何成为跨境电商突…...
WEB安全--SQL注入--Oracle注入
一、Oracle知识点了解 1.1、系统变量与表 版本号:SELECT * FROM V$VERSION 用户名:USER、SYS_CONTEXT(USERENV,SESSION_USER) 库名:ALL_USERS、USER_USERS、DBA_USERS 表名:ALL_TABLES、DBA_TABLES、USER_TABLES 字段名&…...
Unity预制体变体(Prefab Variants)、接口(Interface)、抽象类(Abstract Class)、枚举(Enumeration)
一、预制体变体(Prefab Variants) 预制体变体是什么? 预制体变体是指从同一个基础预制体派生出来的不同版本的预制体。这些变体可以包含不同的组件配置、属性值、子对象或者行为,但它们共享一些共同的基础结构和特性。通过创建预…...
pymol包安装和使用
PyMOL 是一款分子可视化软件,而pymol则是其对应的 Python 包,借助它能够实现对 PyMOL 的编程控制。 主要功能 分子结构可视化:支持展示蛋白质、核酸、小分子等多种分子的 3D 结构。自定义渲染:可对分子的表示方式、颜色以及光照…...
【学习笔记】机器学习(Machine Learning) | 第七章|神经网络(2)
机器学习(Machine Learning) 简要声明 基于吴恩达教授(Andrew Ng)课程视频 BiliBili课程资源 文章目录 机器学习(Machine Learning)简要声明 神经网络在图像识别及手写数字识别中的应用一、神经网络在图像识别中的应用࿰…...
【神经网络与深度学习】model.eval() 模式
引言 在深度学习模型的训练和推理过程中,不同的模式设置对模型的行为和性能有着重要影响。model.eval() 是 PyTorch 等深度学习框架中的关键操作,它用于将模型切换到评估模式(evaluation mode),确保模型在测试和推理阶…...
ASIC和FPGA,到底应该选择哪个?
ASIC和FPGA各有优缺点。 ASIC针对特定需求,具有高性能、低功耗和低成本(在大规模量产时);但设计周期长、成本高、风险大。FPGA则适合快速原型验证和中小批量应用,开发周期短,灵活性高,适合初创企…...
JavaScript 性能优化实战指南
JavaScript 性能优化实战指南 前言 随着前端应用复杂度提升,JavaScript 性能瓶颈日益突出。高效的性能优化不仅能提升用户体验,还能增强系统稳定性和可维护性。本文系统梳理了 JavaScript 性能优化的核心思路、常见场景和实战案例,结合代码…...
Unity3D HUD UI性能优化方案
前言 在Unity3D中实现高性能的HUD UI需要综合考虑渲染效率、CPU开销和内存管理。以下是分步的优化方案: 对惹,这里有一个游戏开发交流小组,大家可以点击进来一起交流一下开发经验呀! 1. 降低Draw Call:合批与图集 …...
晶圆Map图芯片选择显示示例
效果 列表中有四个Mark点,需求是选择某一个点时在Map图中区别显示出来。 实现思路: 根据DataGrid 的行选择 SelectionChanged事件,先循环所有Mark点清除Rectangle的边框大小,再获取选择的芯片,设置Rectangle的边框大小和颜色。 示例代码 1.UI代码 <DataGrid Grid.…...
HarmonyOS实战:自定义时间选择器
前言 最近在日常鸿蒙开发过程中,经常会使用一些时间选择器,鸿蒙官方提供的时间选择器满足不了需求,所以自己动手自定义一些经常会使用到的时间选择器,希望能帮到你,建议点赞收藏! 实现效果 需求分析 默认…...
汽车零部件的EMI抗扰性测试
写在前面 本系列文章主要讲解汽车零部件的EMI抗扰性测试的相关知识,希望能帮助更多的同学认识和了解汽车零部件的EMI抗扰性测试。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 1. 背景介绍 多年以来,电磁干扰(EMI)效应一直是现代电子控制系统中备受关注的一个问题。…...
新能源汽车充电桩管理平台如何利用智慧技术优化资源配置问题?
在“双碳”目标的推动下,我国新能源汽车市场迅猛发展,但充电基础设施的供需失衡问题日益突出。部分区域充电桩利用率低下,而核心城区、高速服务区等场景却面临“一桩难求”的困境。智慧技术的引入为解决这一难题提供了新思路。通过物联网&…...
【zookeeper】--部署3.6.3
文章目录 下载解压创建data和logs配置文件1)创建目录并且编辑 zoo.cfg2)接下来将 node01 的 ZooKeeper 所有文件拷贝至 node02 和 node03。推荐从 node02 和 node03 拷贝4)最后 vim /etc/profile 配置环境变量,环境搭建结束。配完环境变量后 source /etc…...
[低代码] 明道云调用本地部署 Dify 的进阶方法
在低代码开发平台明道云中,集成外部智能服务(如 Dify)可以极大地提升自动化和智能化能力。之前我们介绍了使用“发送自定义 API”节点直接调用本地部署的 Dify 服务的方法,虽然简单直观,但该方式存在一些限制,比如无法设置 Timeout、逻辑复用性差等问题。 为了构建更稳定…...
ICU库交叉编译
交叉编译步骤 Step 1: 先进行本机编译 ./runConfigureICU Linux/gccmake Step 2: 执行交叉编译 source /opt/fsl-imx-fb/4.14-sumo/environment-setup-cortexa9hf-neon-poky-linux-gnueabimkdir cross_install./configure --disable-samples --disable-tests --prefix/medi…...
永磁同步电机高性能控制算法(22)——基于神经网络的转矩脉动抑制算法为什么低速时的转速波动大?
0. 前言 在之前的知乎上发过一些转矩脉动抑制/谐波电流抑制的算法。例如: https://zhuanlan.zhihu.com/p/24723996895https://zhuanlan.zhihu.com/p/24723996895 这些算法基本上都需要先知道谐波的频率。 重复控制这个算法虽然可以抑制掉某个频率及其所有整数倍的…...
Java大厂面试实战:Spring Boot与微服务场景中的技术点解析
Java大厂面试实战:Spring Boot与微服务场景中的技术点解析 第一轮:基础技术了解 面试官:谢飞机,你好。从简历上看,你熟悉Spring Boot,那我们来聊聊它的核心功能吧。Spring Boot有哪些主要的特性ÿ…...
Pycharm 选择Python Interpreter
你的系统可能有多个 Python 环境,比如: macOS 自带的 /usr/bin/python3 你用 brew install python 安装的 /opt/homebrew/bin/python3 你可能还用了虚拟环境(venv 或 conda) PyCharm 默认配置可能用的是一个虚拟环境ÿ…...
文件夹如何打包成jar包
应用场景 主要是:比如 maven 引入一个依赖(其实就是下载了一个 jar 包),然后需要修改 jar 包里面的某个文件,然后再重新打包成 jar 包,如下图: 使用方法 使用压缩工具打开这个 jar 包…...
sqli-labs第九关—‘时间盲注
一:判断闭合类型 先按照之前的判断方式判断,发现无论输入什么都显示You are in.......... 可以考虑使用时间盲注: 二:时间盲注Time-based Blind: 1.解释: 通过时间延迟判断结果 2.核心原理:…...
10.15 LangChain v0.3重磅升级:Tool Calling技术颠覆大模型工具调用,效率飙升300%!
LangChain v0.3 技术生态与未来发展:支持 Tool Calling 的大模型 关键词:LangChain Tool Calling, 大模型工具调用, @tool 装饰器, ToolMessage 管理, Few-shot Prompting 1. Tool Calling 的技术革新 LangChain v0.3 的工具调用(Tool Calling)功能标志着大模型应用开发进…...
【C++】哈希的概念与实现
1.哈希概念 通过某种函数使元素的存储位置与它的关键码之间能够建立一一映射的关系,可以不经过任何比较,一次直接从表中得到要搜索的元素。 当向该结构中: 插入元素: 根据待插入元素的关键码,以此函数计算出该元素的…...
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决 Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决1. 问题现象与初步分析2 . 原因探究:代理机制对分布式锁生命周期的干扰3. 问题复现伪代码4. 解决方案࿱…...
vue Element-ui对图片上传和选用时的比例控制
vue Element-ui对图片上传和选用时的比例控制 在后台上传图片和选用已经上传的图片时,往往会因为图片的比例控制不到位导致在客户端渲染时效果差强人意,虽然可以在操作时选择合适的比例上传,但必要的控制还是能完成渲染时良好的体验…...
UE5在C++项目中判断不同平台
在Unreal Engine 5的C代码中,可以通过以下方法判断当前运行的平台(如Android、Windows、iOS),并根据平台执行不同的逻辑: 方法1:使用预处理器宏(编译时判断) Unreal Engine提供了一…...
用 CodeBuddy 实现「IdeaSpark 每日灵感卡」:一场 UI 与灵感的极简之旅
项目起点:一次随手的灵感 有时候,灵感稍纵即逝,尤其是面对屏幕发呆的时候。那天我忽然想到——要是能有一个每天弹出一句创意提示、灵感金句的应用就好了,最好配上简洁但有氛围感的 UI,像抽一张卡片一样,轻…...
std::ranges::views::as_const 和 std::ranges::as_const_view
std::ranges::views::as_const 和 std::ranges::as_const_view 是 C23 引入的视图适配器,用于生成一个不可变的视图,确保通过该视图访问元素时,元素被视为常量。以下是详细说明和示例: 基本概念 功能: 将输入范围的元素…...
3D 数据交换格式(.3DXML)简介
3DXML 是一种基于 XML 的 3D 数据交换格式,由达索系统(Dassault Systmes)开发,主要用于其 CATIA、SOLIDWORKS 和 3DEXPERIENCE 等产品中。 基本概述 全称:3D XML开发者:达索系统主要用途:3D…...
深度解析3D模型生成器:基于StyleGAN3与PyTorch3D的多风格生成工具开发实战
引言:跨模态生成的革命性突破 在元宇宙与数字孪生技术蓬勃发展的今天,3D内容生成已成为制约产业发展的关键瓶颈。传统建模方式依赖专业软件和人工操作,而基于深度学习的生成模型正颠覆这一范式。本文将深入解析如何构建支持多风格生成的3D模…...
DTAS 3D多约束装配助力悬架公差分析尺寸链计算:麦弗逊/双叉臂/多连杆/H臂一网打尽
摘要:汽车四轮定位参数与悬架密切相关。汽车悬架对于车辆的行驶性能、安全性和舒适性至关重要。DTAS 3D提供了各类型悬架的公差仿真分析方法。 关键字:DTAS 3D、前后悬架、公差仿真分析、 运动耦合 一、悬架公差分析综述 悬架是车身(或车架…...
CRMEB多商户预约服务上门师傅端
随着科技的不断发展,人们对于生活品质的要求也在不断提高。在这个过程中,各种便捷的上门服务应运而生,为我们的生活带来了极大的便利。而CRMEB多商户预约服务上门师傅端正是这样一款致力于为用户提供专业、高效、便捷的上门服务的应用。 一、…...
labview硬件开发板——LED流水灯
函数 : int DoSetV12( unsigned char chan, unsigned char state); 功能 :设置 OUT0—3 的输出状态,输入参数为 8 位字符型, Chan:4 位要设置的通道,0 对应 OUT1……3 对应 OUT4 ( 注意:开…...
linux——mysql故障排查与生产环境优化
目录 一,mysql数据库常见的故障 1,故障现象1 2,故障现象2 3,故障现象3 4,故障现象4 5,故障现象5 6,故障现象6 二&…...
MongoDB及spring集成
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统 用文档存数据,每个文档可以看作是一个键值对集合,类似于 JSON 对象 MongoDB 支持索引以提高查询性能,并且可以在任何属性上创建索引 文档(Document) M…...
一发入魂:极简解决 SwiftUI 复杂视图未能正确刷新的问题(下)
概述 各位似秃非秃小码农们都知道,在 SwiftUI 中视图是状态的函数,这意味着状态的改变会导致界面被刷新。 但是,对于有些复杂布局的 SwiftUI 视图来说,它们的界面并不能直接映射到对应的状态上去。这就会造成一个问题:状态的改变并没有及时的引起 UI 的变化。 如上图所示…...
关于我在使用stream().toList()遇到的问题
关于我在使用stream().toList()遇到的问题 问题描述 在测试以上程序的时候抛出了空指针异常 于是我以为是我数据库中存在null字段,但查看后发现并不存在为null的数据 问题排查 起初我以为问题出现在sort排序方法这,事实也确实是,当我把s…...
如何通过生成式人工智能认证(GAI认证)提升自己的技能水平?
当生成式人工智能从实验室走向生产线,职场人正面临一个关键抉择:是被动等待技术浪潮的冲刷,还是主动构建适应未来的能力护城河?职业技能培训的终极目标,早已超越“掌握工具”的初级阶段,转向“构建技术认知体系”的深层需求。生成式人工智能认证(GAI认证)的兴起,正是这…...
通讯协议串口 | 485标准
485通讯(RS-485)详解 一、基本概念与核心原理 定义与标准 RS-485(又称EIA-485)是一种由美国电子工业协会(EIA)制定的差分信号串行通信标准,属于OSI模型的物理层协议。它专为工业环境设计&#…...
新能源充电桩智慧管理系统:未来新能源汽车移动充电服务发展前景怎样?
随着全球新能源汽车保有量的持续攀升,传统固定充电桩建设速度已难以满足用户日益增长的补能需求。在这一背景下,移动充电服务作为充电基础设施的重要补充,正展现出巨大的发展潜力。政策支持、技术进步(如快充、智能调度࿰…...
【强化学习】#6 n步自举法
主要参考学习资料:《强化学习(第2版)》[加]Richard S.Suttion [美]Andrew G.Barto 著 文章源文件:https://github.com/INKEM/Knowledge_Base 概述 n步时序差分方法是蒙特卡洛方法和时序差分方法更一般的推广。将单步Sarsa推广到n…...
双指针算法:原理与应用详解
文章目录 一、什么是双指针算法二、双指针算法的适用场景三、双指针的三种常见形式1. 同向移动指针2. 相向移动指针3. 分离指针 四、总结 一、什么是双指针算法 双指针算法(Two Pointers Technique)是一种在数组或链表等线性数据结构中常用的高效算法技…...
小土堆pytorch--神经网路的基本骨架(nn.Module的使用)卷积操作
小土堆pytorch–神经网路的基本骨架(nn.Module的使用) 对于官网nn.Module操作的解释 在pytorch官网可以看到 对于上述forward函数的解释: 示例代码 import torch from torch import nnclass Test(nn.Module): # 继承神经网路的基本骨架…...