当前位置: 首页 > news >正文

RabbitMQ可靠性进制

文章目录

    • 1.生产者可靠性
      • 生产者重连
      • 生产者确认
      • 小结
    • 2. MQ的可靠性
      • 数据持久化
      • LazyQueue
      • 小结
    • 3. 消费者的可靠性
      • 消费者确认机制
      • 消费者失败处理方案
      • 业务幂等性
        • 唯一消息ID
        • 业务判断
      • 兜底方案
        • 业务判断
      • 兜底方案


1.生产者可靠性

生产者重连

在某些场景下由于网络波动,可能就会出现客户端连接MQ失败的情况,,此时我们可以在Spring配置文件中开启连接失败后的重连机制:

spring:rabbitmq:connection-timeout: 1s # 设置MQ的连接超时时间template:retry:enabled: true # 开启超时重试机制initial-interval: 1000ms # 失败后的初始等待时间multiplier: 1 # 失败后下次的等待时长倍数,下次等待时长 = initial-interval * multipliermax-attempts: 3 # 最大重试次数

需要注意的是,虽然这个重试机制在网络不稳定的时候可以有效提高消息的发送成功率。而SpringAMQP提供的重试机制是阻塞式的重试,也就是说这个操作并不是异步的会导致主线程被阻塞,从而影响业务性能。

如果对于业务性能有要求,建议禁用重试机制。如果非要使用,一定要合理配置等待时长和重试次数,或者采用异步线程来处理发送消息的代码

生产者确认

RabbitMQ提供了生产者消息确认机制,包括Publisher ConfirmPublisher Return两种,在MQ成功收到消息后会返回确认消息给生产者。而返回的结果又一下几种情况:

  • 消息投递到了MQ,但是路由失败,此时会通过Publisher Return返回路由异常原因,然后返回ACK,并return一个路由失败的消息
    • 路由失败一般不会出现,路由失败可能是这个路由并没有绑定队列,或者说代码写的有问题
    • 所以说路由失败这种情况只要开发配置和代码没有问题,几乎不可能出现
  • 第二种场景就是临时消息投递到了MQ,并且入队成功,返回ACK,告诉发送者消息投递成功
  • 第三种场景就是持久化消息投递到了MQ,并且消息持久化到磁盘后,才返回ACK告诉发送者消息投递成功

除了以上三种场景消息发送成功会返回ACK,其它的情况都会返回NACK,比如说持久化到磁盘失败了,内存满了导致内存丢失。

其中acknack属于Publisher Confirm机制,ack是投递成功;nack是投递失败。而return则属于Publisher Return机制。

通过以上机制基本能保证消息发生成功,只要失败就进行重发

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码实现生产者确认机制:

在Spring配置文件中添加对应配置文件:

spring:rabbitmq:publisher-confirm-type: correlated # 开启publisher confirm机制,并设置confirm类型publisher-returns: true # 开启publisher return机制

这里publisher-confirm-type有三种模式可选:

  • none:关闭confirm机制
  • simple:同步阻塞等待MQ的回执
  • correlated:MQ异步回调返回回执

一般我们推荐使用correlated,回调机制。

定义ReturnCallback

每个RabbitTemplate只能配置一个ReturnCallback,因此我们可以在配置类中统一设置。我们在publisher模块定义一个配置类:

@Configuration
@Slf4j
public class MqConfig implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {@Overridepublic void returnedMessage(ReturnedMessage returnedMessage) {log.debug("收到return callback消息:exchange:{},code:{},replyText:{},returnMsg:{}",returnedMessage.getExchange(),returnedMessage.getReplyCode(),returnedMessage.getReplyText(),returnedMessage.getMessage());}});}
}

定义ConfirmCallback

由于每个消息发送时的处理逻辑不一定相同,因此ConfirmCallback需要在每次发消息时定义。具体来说,是在调用RabbitTemplate中的convertAndSend方法时,多传递一个参数:

@Test
void confirmCallback() throws InterruptedException {// 1.创建CorrelationDataCorrelationData correlationData = new CorrelationData();// 2. 给Future添加confirmCallbackcorrelationData.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {@Overridepublic void onFailure(Throwable ex) {// 该异常是Spring AMQP的异常,和RabbitMQ的无关log.error("future消息发送失败:{}",ex);}@Overridepublic void onSuccess(CorrelationData.Confirm result) {if (result.isAck()){log.debug("消息发送成功,收到确认ACK");} else {log.error("消息发送失败,收到NACK,原因: {}",result.getReason());}}});// 3. 发送消息rabbitTemplate.convertAndSend("test.direct", "red", "hello, confirm callback", correlationData);
}

这里的CorrelationData中包含两个核心的东西:

  • id:消息的唯一标示,MQ对不同的消息的回执以此做判断,避免混淆(默认构造方法使用了UUID)

    public CorrelationData() {this.id = UUID.randomUUID().toString();
    }
    
  • SettableListenableFuture:回执结果的Future对象,利用回调函数异步处理确认消息

注意事项

开启生产者确认也是比价消耗MQ的性能的,一般也是不建议开启的,生产者确认消息主要有以下几种场景:

  • 一种是路由失败,一般是RoutingKey失败导致的,还有就是交换机名称错误,这也就是编码问题
  • MQ内部故障,这种场景出现概率比价低除非对消息可靠性要求较高的业务才需要开启,并且只要开启ConfirmCallback处理NACK就可以了

因为生产者确认机制需要额外的网络何系统资源开销,所以如果非要使用生产者确认机制,只需要开启Publisher Confirm机制,并且只是处理NACK消息,进行指定次数的重试,如果依然失败记录异常消息即可。

Publisher Return这种一般由于配置或者编码出现问题的根本不需要关心,因为路由出现问题一般是业务代码的问题

小结

如何保证生产发送消息的可靠性?

  1. 首先我们可以在配置文件中开启生产者重连机制,避免网络波动场景下客户端连接MQ失败
  2. 如果是其他原因导致的失败,RabbitMQ还支持生产者确认机制,接着开启生产者确认机制,根据返回的ACK和NAC来确认是否重发消息
  3. 通过以上手段基本可以保证生产者发送消息的可靠性
  4. 但是因为生产者重连和确认机制会增加网络和系统资源的开销,所以在大多数场景下无需开启确认和重连机制,除非对消息可靠性要求较高

2. MQ的可靠性

生产者在发送的消息到达MQ之后,如果MQ不能及时保存,也会导致消息丢失,所以MQ的可靠性我们也要非常关注。

  • 一旦MQ宕机,内存中的消息会丢失
  • 内存空间有限,当消费者故障或处理过慢时,会导致消息积压,引发MQ阻塞

如果采用的是非持久化的消息(纯内存),当不断往MQ中发送消息,MQ的队列存储不下的时候就会发生PageOut,将存放不下的一部老消息存放到磁盘中,在PageOut的那一瞬间是无法处理消息的,也就是阻塞状态。可能就会导致消息堆积,影响性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据持久化

为了提升MQ的性能,默认情况MQ的数据都是在内存中临时存储的,只要一重启就会丢失,为了保证数据的可靠性就必须去配置数据持久化,持久化又包括:

  • 交换机的持久化
  • 队列的持久化
  • 消息的持久化

如下图在创建队列的时候就能指定创建持久化队列

设置为Durable就是持久化模式,Transient就是临时模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在发送消息的时候也需要指定消息为持久化的消息,而SpringAMQP提供的发送消息的方法默认就是发送的持久化的消息。

使用持久化的消息,将每次发送的消息备份到磁盘中,过一段时间清空内存中已经持久化的消息,保证消息的一个安全性,也就说某一时刻内存和磁盘都会存在同一份消息,只是后续内存会做一个清空,在清空内存的时候会有一定的性能下降,但并不会出现像存内存那样的PageOut直接阻塞无法处理消息

LazyQueue

从RabbitMQ的3.6.0版本开始,就增加了Lazy Queues的模式,也就是惰性队列。惰性队列的特征如下:

  • 接收到消息后直接存入磁盘而非内存(内存中指保留最近的一部分消息)
  • 消费者要消费消息时才会从磁盘中读取并加载到内存(也就是懒加载)
  • 支持数百万条的消息存储

在3.12版本后,所有队列都是Lazy Queue模式,无法更改

在添加队列的时候,添加x-queue-mod=lazy参数即可设置队列为Lazy模式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码配置Lazy模式

@Bean
public Queue lazyQueue(){return QueueBuilder.durable("lazy.queue").lazy() // 开启Lazy模式.build();
}

使用声明式注解

@RabbitListener(queuesToDeclare = @Queue(name = "lazy.queue",durable = "true",arguments = @Argument(name = "x-queue-mode", value = "lazy")
))
public void listenLazyQueue(String msg){log.info("接收到 lazy.queue的消息:{}", msg);
}

小结

RabbitMQ如何保证消息的可靠性

  1. 首先通过配置可以让交换机、队列、以及发送的消息都持久化。这样队列中的消息会持久化到磁盘,MQ重启消息依然存在。
  2. RabbitMQ在3.6版本引入了LazyQueue,并且在3.12版本后会称为队列的默认模式。LazyQueue会将所有消息都持久化。
  3. 开启持久化和生产者确认时, RabbitMQ只有在消息持久化完成后才会给生产者返回ACK回执

3. 消费者的可靠性

当RabbitMQ向消费者投递消息以后,需要知道消费者处理消息的状态如何,因为不能保证消息投递给消费者并不代表就一定被正确消费了,因为消费者也会出现很多的异常情况,比如说:

  • 消息在投递过程中出现了网络波动
  • 消费者收到了消息,但是消费者机器突然宕机了
  • 消费者接受到消息后,没有正确处理消息导致异常

除了上诉还有其他的异常情况,从而导致消息丢失,因此RabbitMQ还需要知道消费者的处理状态,消费者处理失败就可以进行重新投递消息

消费者确认机制

为了确认消费者是否成功处理消息,RabbitMQ提供了消费者确认机制(Consumer Acknowledgement)。即:当消费者处理消息结束后,应该向RabbitMQ发送一个回执,告知RabbitMQ自己消息处理状态。回执有三种可选值:

  • ack:成功处理消息,RabbitMQ从队列中删除该消息
  • nack:消息处理失败,RabbitMQ需要再次投递消息
  • reject:消息处理失败并拒绝该消息,RabbitMQ从队列中删除该消息

一般使用reject这种方式情况比较少,消息处理失败比如说消息格式有问题啥的(消息转换异常),而这种情况一般使用try/chtch机制捕获,消息处理成功返回ACK,失败就返回nack。

由于消息回执的处理代码比较统一,因此SpringAMQP帮我们实现了消息确认。并允许我们通过配置文件设置ACK处理方式,有三种模式:

  • none:不处理。即消息投递给消费者后立刻ack,消息会立刻从MQ删除。非常不安全,不建议使用
  • manual:手动模式。需要自己在业务代码中调用api,发送ackreject,存在业务入侵,但更灵活
  • auto:自动模式。SpringAMQP利用AOP对我们的消息处理逻辑做了环绕增强,当业务正常执行时则自动返回ack. 当业务出现异常时,根据异常判断返回不同结果:
    • 如果是业务异常,会自动返回nack
    • 如果是消息处理或校验异常,自动返回reject;

返回Reject的常见异常有:

Starting with version 1.3.2, the default ErrorHandler is now a ConditionalRejectingErrorHandler that rejects (and does not requeue) messages that fail with an irrecoverable error. Specifically, it rejects messages that fail with the following errors:

  • o.s.amqp…MessageConversionException: Can be thrown when converting the incoming message payload using a MessageConverter.
  • o.s.messaging…MessageConversionException: Can be thrown by the conversion service if additional conversion is required when mapping to a @RabbitListener method.
  • o.s.messaging…MethodArgumentNotValidException: Can be thrown if validation (for example, @Valid) is used in the listener and the validation fails.
  • o.s.messaging…MethodArgumentTypeMismatchException: Can be thrown if the inbound message was converted to a type that is not correct for the target method. For example, the parameter is declared as Message but Message is received.
  • java.lang.NoSuchMethodException: Added in version 1.6.3.
  • java.lang.ClassCastException: Added in version 1.6.3.

通过Spring的配置文件,可以配置SpringAMQP的ACK处理方式()

spring:rabbitmq:listener:simple:acknowledge-mode: auto # 自动ack

消费者失败处理方案

根据上诉的消费者处理机制,消费者出现异常后消息会不断重新进入到队列会哦只能,再次重新尝试发送给消费者,那么此时消费者再次消费消息又报错,消息又会重新入队,知道消息处理完成。

假设极端情况消费者就是无法处理该消息,那么消息就会无限循环,导致mq的消息处理表现造成不小的系统开销,影响系统性能。

不过出现这种极端情况的概率是非常低的,针对上诉情况Spring又为开发者提供了消费者失败重试机制,在消费者出现异常的时候利用本地重试,而不是不断的将消息发送到mq的队列中,

修改Spring的配置文件

spring:rabbitmq:listener:simple:retry:enabled: true # 开启消费者失败重试initial-interval: 1000ms # 初识的失败等待时长为1秒multiplier: 1 # 失败的等待时长倍数,下次等待时长 = multiplier * last-intervalmax-attempts: 3 # 最大重试次数stateless: true # true无状态;false有状态。如果业务中包含事务,这里改为false
  • 消费者在失败后消息没有重新回到MQ无限重新投递,而是在本地重试了3次
  • 本地重试3次以后,抛出了AmqpRejectAndDontRequeueException异常。查看RabbitMQ控制台,发现消息被删除了,说明最后SpringAMQP返回的是reject

结论:

  • 开启本地重试时,消息处理过程中抛出异常,不会requeue到队列,而是在消费者本地重试
  • 重试达到最大次数后,Spring会返回reject,消息会被丢弃

业务幂等性


在程序开发中业务幂等性指的是同一个业务,执行一次或者执行多次对业务状态的影响是一致的,也就执行一次或者多次是没有什么区别的。

比如:

  • 使用id来删除一条数据
  • 使用id来查询一条数据

数据的删除和查询操作通常都是幂等的,但是数据的更新操作往往不是幂等的,如果重复执行就可能出现不可预期的结果。比如说:

  • 取消订单:取消订单在恢复库存的时候,如果用户点击多次就可能出现库存重复增加的情况
  • 退款业务:重复的退款操作会对商家操作不小的损失。

所以在编写业务代码的时候要尽可能的避免业务被重复执行,然后实际业务中有很多业务场景都会被重复提交,比如说:

  • 用户网络卡顿频繁提交表单
  • 多个服务之间的调用重试
  • MQ的将同一条消息重复投递

因此,我们必须想办法保证消息处理的幂等性。这里给出两种方案:

  • 唯一消息ID
  • 业务状态判断
唯一消息ID

唯一消息ID其实就是个每一条消息一个UUID,然后将消息投递给消费者。

  1. 消费者接收到消息将消息处理后,将消息ID保存到数据库
  2. 如果下次又处理相同的消息,去数据库中查询是否存在即可

SpringAMQP的MessageConverter自带了MessageID的功能,我们只要开启这个功能即可。

@Bean
public MessageConverter messageConverter(){// 1.定义消息转换器Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();// 2.配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息jjmc.setCreateMessageIds(true);return jjmc;
}

该方案需要增加一个查和一个写数据库的操作对性能上有一定影响,还有一个需要保存消息ID也增加了耦合性,对业务有一定侵入

业务判断

我们还可以通过业务逻辑的判断来保证业务的幂等性。假设有一个支付场景,有已支付和未支付状态,在修改前判断是否已经支付,支付了就放弃本次操作。

通过MySQL的行锁即可实现,只有当订单为未支付的时候SQL才能执行修改成已支付状态

UPDATE `order` SET status = ? WHERE id = ? AND status = 1

兜底方案

MQ能保证99%的可能,但并不是百分之百,所以在某些时候我们可以做一些兜底方案,保证多个服务之间的订单状态一致。

比如说支付服务支付完成后MQ消息通知失败,就可以通过定时任务主动去查询支付状态来去更新订单状态


案需要增加一个查和一个写数据库的操作对性能上有一定影响,还有一个需要保存消息ID也增加了耦合性,对业务有一定侵入

业务判断

我们还可以通过业务逻辑的判断来保证业务的幂等性。假设有一个支付场景,有已支付和未支付状态,在修改前判断是否已经支付,支付了就放弃本次操作。

通过MySQL的行锁即可实现,只有当订单为未支付的时候SQL才能执行修改成已支付状态

UPDATE `order` SET status = ? WHERE id = ? AND status = 1

兜底方案

MQ能保证99%的可能,但并不是百分之百,所以在某些时候我们可以做一些兜底方案,保证多个服务之间的订单状态一致。

比如说支付服务支付完成后MQ消息通知失败,就可以通过定时任务主动去查询支付状态来去更新订单状态


相关文章:

RabbitMQ可靠性进制

文章目录 1.生产者可靠性生产者重连生产者确认小结 2. MQ的可靠性数据持久化LazyQueue小结 3. 消费者的可靠性消费者确认机制消费者失败处理方案业务幂等性唯一消息ID业务判断 兜底方案业务判断 兜底方案 1.生产者可靠性 生产者重连 在某些场景下由于网络波动&#xff0c;可能…...

PHP优化技术

最近在学习php语言&#xff0c;打算用来提升开发小项目的效率。下面是php项目中常见的优化手段。 1、引起php性能问题的原因 &#xff08;1&#xff09;php语法使用不当 &#xff08;2&#xff09;使用php做了它不擅长的事 &#xff08;3&#xff09;用php连接的服务不给力 &…...

【Go类库分享】Go expr 通用表达式引擎

【Go类库分享】Go expr 通用表达式引擎 官方教程&#xff1a;https://expr-lang.org/docs/language-definition 官方Github&#xff1a;https://github.com/expr-lang/expr 文章所含代码地址&#xff1a;https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-d…...

线性代数(1)用 excel 计算鸡兔同笼

线性代数excel计算鸡兔同笼 案例&#xff1a;鸡兔同笼问题的三种解法&#xff08;递进式教学&#xff09;一、问题描述二、方程式解法&#xff08;基础版&#xff09;步骤解析 三、线性代数解法&#xff08;进阶版&#xff09;1. 方程组转化为矩阵形式2. 矩阵求解&#xff08;逆…...

Docker基础知识介绍

Docker基础篇 必须要在Linux环境下才能运行&#xff0c;windows下运行也是安装虚拟机后才能下载安装运行 下载安装 linux 依次执行下边步骤 更新 yum yum update 卸载旧的Docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \do…...

机器人交社保属于“无稽之谈”?

今晨浏览社交网站&#xff0c;惊奇地看到“给机器人上社保”的网页搜索结果竟然多达“约 3,280,000个”。所以被称为“无稽之谈”和“本质上是利用社保之名收税”就实不为过&#xff0c;而且还会让人读罢笑得喷饭&#xff1a;“连搞笑大王赵本山见了&#xff0c;也定会拱手作揖…...

接口测试和功能测试的区别

接口测试和功能测试的区别 一 **接口测试概述**1.1 定义1.2 优缺点 二 **功能测试概述**2.1 定义2.2 优缺点 三 **主要区别**四 两者在测试点的区别4.1 **接口测试的测试点**4.2 **功能测试的测试点**4.3 **接口测试 vs. 功能测试的测试点对比** 五 区别类比**例子背景**&#…...

人工智能中的线性代数基础详解

‌ 线性代数是人工智能领域的重要数学基础之一,是人工智能技术的底层数学支柱,它为数据表示、模型构建和算法优化提供了核心工具。其核心概念与算法应用贯穿数据表示、模型训练及优化全过程。更多内容可看我文章:人工智能数学基础详解与拓展-CSDN博客 一、基本介绍 …...

nginx不在默认的yum仓库的解决方法

1、添加 Nginx 官方仓库 epel-release 是 Extra Packages for Enterprise Linux 的仓库&#xff0c;包含了 nginx 等常用软件。 sudo yum install -y epel-release sudo yum install -y nginx 2、手动添加 Nginx 仓库 如果 epel-release 不可用&#xff0c;可以手动添加 Ng…...

IXTUR气控永磁铁:以高精度气控和稳定磁场,为机器人应用提供稳定抓取力

在现代工业生产和物流领域&#xff0c;物料的抓取与搬运是影响生产效率和成本控制的重要环节。传统夹爪在面对不同材质、形状和重量的物体时&#xff0c;常常存在适应性差、抓取不稳定、操作复杂等问题&#xff0c;导致生产流程中频繁出现停机调整&#xff0c;增加了人工干预成…...

【uni-app运行错误】SassError: expected selector @import “@/uni.scss“;

ERROR in ./src/pages/biddingViews/address_add.vue?vue&typestyle&index0&id41672bf3&scopedtrue&langscss& (./node_modules/vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-22[0].rules[0].use[1]!./node_modules/dcloud…...

堆排序:力扣215.数组中的第K个大元素

一、问题描述 在一个整数数组 nums 中&#xff0c;需要找出第 k 个最大的元素。这里要注意&#xff0c;我们要找的是数组排序后的第 k 个最大元素&#xff0c;而不是第 k 个不同的元素。例如&#xff0c;对于数组 [3,2,1,5,6,4]&#xff0c;当 k 2 时&#xff0c;第 2 个最大…...

【网络协议】应用层协议HTTPS

文章目录 为什么引入HTTPS&#xff1f;基本概念加密的基本过程对称加密非对称加密中间人攻击证书 为什么引入HTTPS&#xff1f; 由于HTTP协议在网络传输中是明文传输的&#xff0c;那么当传输一些机密的文件或着对钱的操作时&#xff0c;就会有泄密的风险&#xff0c;从而引入…...

网络安全防护总体架构 网络安全防护工作机制

1 实践内容 1.1 安全防范 为了保障"信息安全金三角"的CIA属性、即机密性、完整性、可用性&#xff0c;信息安全领域提出了一系列安全模型。其中动态可适应网络安全模型基于闭环控制理论&#xff0c;典型的有PDR和P^2DR模型。 1.1.1 PDR模型 信息系统的防御机制能…...

图像处理篇---图像预处理

文章目录 前言一、通用目的1.1 数据标准化目的实现 1.2 噪声抑制目的实现高斯滤波中值滤波双边滤波 1.3 尺寸统一化目的实现 1.4 数据增强目的实现 1.5 特征增强目的实现&#xff1a;边缘检测直方图均衡化锐化 二、分领域预处理2.1 传统机器学习&#xff08;如SVM、随机森林&am…...

探针泄露(WEB)

##解题思路 题目提示是探针泄露&#xff0c;未及时删除的探针可能造成严重的数据泄露 探针的文件常见命名为tz.php&#xff0c;访问它 对于php相关参数&#xff0c;我们是可以点击的&#xff0c;点击phpinfo访问 跳转后搜索flag&#xff0c;得到flag...

Webpack总结

Webpack是一个前端模块打包工具。它可以将多个模块按照依赖关系进行静态分析&#xff0c;并生成一个或多个打包后的文件。 Webpack的核心概念包括entry&#xff08;入口&#xff09;、output&#xff08;输出&#xff09;、loader&#xff08;加载器&#xff09;和plugin&…...

什么是物理信息神经网络PINN

定义原理 物理信息神经网络(PINN)是一种创新的机器学习方法,将深度学习与物理知识相结合,旨在解决偏微分方程(PDE)相关问题。PINN的核心思想是在神经网络的训练过程中引入物理定律,从而提高模型的泛化能力和预测精度。 PINN的工作原理基于以下关键步骤: 构建神经网络…...

Java面向对象(中)

面向对象(中) 1.继承性 继承性的好处&#xff1a; 减少了代码的冗余&#xff0c;提高了代码的复用性。 便于功能的拓展。 为多态性的使用提供了前期。 格式&#xff1a; class A extends B {} A:子类&#xff0c;派生类&#xff0c;subclass。 B&#xff1a;父类&#x…...

ospf单区域

OSPF单区域是指将整个自治系统&#xff08;AS&#xff09;内的所有路由器划分到同一个逻辑区域&#xff08;Area 0&#xff0c;即骨干区域&#xff09;中运行的OSPF协议模式。以下是其核心要点&#xff1a; 一、定义与核心特点 ‌区域统一性‌ 所有路由器均属于同一区域&…...

kali之nmap

kali之nmap Nmap&#xff08;Network Mapper&#xff09;是 Kali Linux 中最著名的网络扫描工具之一&#xff0c;广泛用于网络发现、端口扫描、服务识别、操作系统检测等任务。它是一个功能强大且灵活的开源工具&#xff0c;适用于渗透测试、网络管理和安全审计。 1. Nmap 的主…...

【Rust基础】排序和分组

排序 简单排序 整数排序 #[test] fn test_sort(){let mut list vec![1, 5, 3, 2, 4];list.sort(); //✔assert_eq!(list, vec![1, 2, 3, 4, 5]); }小数排序 #[test] fn test_sort(){let mut list vec![1, 5, 3, 2, 4];//❌ 不能直接使用sort&#xff0c;因为f32和f64未实现O…...

HarmonyOS NEXT开发实战——HUAWEI DevEco Studio 开发指南

概述 HUAWEI DevEco Studio&#xff08;以下简称 DevEco Studio&#xff09;是基于 IntelliJ IDEA Community 开源版本打造的一站式开发平台&#xff0c;专为 HarmonyOS 系统上的应用和元服务&#xff08;以下简称 应用/元服务&#xff09;提供高效的开发环境。 作为一款专业…...

R 语言科研绘图 --- 密度图-汇总

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

【拒绝算法PUA】LeetCode 2270. 分割数组的方案数

系列文章目录 【拒绝算法PUA】0x00-位运算 【拒绝算法PUA】0x01- 区间比较技巧 【拒绝算法PUA】0x02- 区间合并技巧 【拒绝算法PUA】0x03 - LeetCode 排序类型刷题 【拒绝算法PUA】LeetCode每日一题系列刷题汇总-2025年持续刷新中 C刷题技巧总结&#xff1a; [温习C/C]0x04 刷…...

k8s 配置两个deployment主机级别互斥部署

在 Kubernetes 中&#xff0c;要实现两个 Deployment 的 Pod 在主机级别互斥部署&#xff0c;可以使用 podAntiAffinity 配置。通过设置 podAntiAffinity&#xff0c;可以确保两个 Deployment 的 Pod 不会被调度到同一节点上。 实现步骤 定义 Deployment&#xff1a; 为每个…...

Axure大屏可视化原型模板及素材:数据可视化的高效解决方案

数据可视化已成为企业决策、运营分析、市场洞察的重要工具。数据可视化大屏&#xff0c;作为数据展示和交互的直观平台&#xff0c;能够实时呈现关键数据&#xff0c;帮助企业快速做出决策。Axure作为原型设计领域的领先工具&#xff0c;以其丰富的组件库、强大的交互设计能力和…...

AGI大模型(2):GPT:Generative Pre-trained Transformer

1 Generative Pre-trained Transformer 1.1 Generative生成式 GPT中的“生成式”指的是该模型能够根据输入自动生成文本内容,而不仅仅是从已有的文本库中检索答案。 具体来说: 生成(Generative):GPT是一个生成式AI模型,能够根据给定的提示(Prompt)动态生成连贯、…...

Profinet转Profinet以创新网关模块为核心搭建西门子和欧姆龙PLC稳定通讯架构案例​

你是否有听过PROFINET主站与PROFINET主站之间需要做数据通讯有需求&#xff1f; 例如西门子1500与霍尼韦尔DCS系统两个主站之间的通讯。应用于PROFINET为主站设备还有欧姆龙、基恩士、罗克韦尔、施耐德、GE、ABB等品牌的PLC或DCS、FCS等平台。在生产或智能领域有通讯需求。两头…...

函数调用汇编

目录 一、核心概念 二、函数调用过程&#xff08;以 x86 cdecl 为例&#xff09; 三、x86 vs x64 区别 四、示例分析&#xff08;C代码 → 汇编&#xff09; 五、常见问题 一、核心概念 调用约定 (Calling Convention) 规定参数传递顺序&#xff08;如 cdecl 是右到左&…...

LabVIEW 线性拟合

该 LabVIEW 程序实现了 线性拟合&#xff08;Linear Fit&#xff09;&#xff0c;用于计算给定一组数据点的斜率&#xff08;Slope&#xff09;和截距&#xff08;Intercept&#xff09;&#xff0c;并将结果可视化于 XY Graph 中。本案例适用于数据拟合、实验数据分析、传感器…...

在办公电脑上本地部署 70b 的 DeepSeek 模型并实现相应功能的大致步骤

以下是为客户在办公电脑上本地部署 70b 的 DeepSeek 模型并实现相应功能的大致步骤&#xff1a; 硬件准备&#xff1a; 70b 模型对硬件要求较高&#xff0c;确保办公电脑有足够强大的 GPU&#xff08;例如 NVIDIA A100 等高端 GPU&#xff0c;因为模型规模较大&#xff0c;普通…...

国产编辑器EverEdit - 脚本(解锁文本编辑的无限可能)

1 脚本 1.1 应用场景 脚本是一种功能扩展代码&#xff0c;用于提供一些编辑器通用功能提供不了的功能&#xff0c;帮助用户在特定工作场景下提高工作效率&#xff0c;几乎所有主流的编辑器、IDE都支持脚本。   EverEdit的脚本支持js(语法与javascript类似)、VBScript两种编程…...

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域&#xff0c;想要入行该领域&#xff0c;我们需要付出足够多的时间和精力好好学习相关知识&#xff0c;才可以获得一份不错的工作&#xff0c;那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…...

H5端vue3 SSR 项目报错小计

H5端vue3 SSR 项目报错小计 环境 "vue-router": "^4.1.6" "vue": "^3.2.45", "vant": "^3.4.9",报错复现 ①.页面刷新点击 RouterLink 跳转链接, 页面无法跳转 问题排查 ①.去除 van-popup 使用的 teleport“…...

【Node.js入门笔记4---fs 目录操作】

Node.js入门笔记4 Node.js---fs 目录操作一、目录操作1.fs.mkdir()&#xff1a;创建目录。异步&#xff0c;非阻塞。创建单个目录创建多个目录创建目前之前需要确认是否存在&#xff1a; 2. fs.mkdirSync()&#xff1a;用于创建一个新的目录。异步&#xff0c;非阻塞。3.fs.rmd…...

xcode 旧版本、历史版本下载

下载链接&#xff1a;https://developer.apple.com/download/all/ 版本发布日志&#xff1a;https://developer.apple.com/documentation/xcode-release-notes 需要登录开发者账号&#xff0c;搜索下载即可&#xff1a; 再贴一下网友做的版本统计macOS 版本对应的 Xcode 版本&…...

(十一) 人工智能 - Python 教程 - Python元组

更多系列教程&#xff0c;每天更新 更多教程关注&#xff1a;xxxueba.com 星星学霸 1 元组&#xff08;Tuple&#xff09; 元组是有序且不可更改的集合。在 Python 中&#xff0c;元组是用圆括号编写的。 实例 创建元组&#xff1a; thistuple ("apple", "b…...

【计算机视觉】工业表计读数(1)--基于关键点检测的读数识别方案

随着工业自动化和智能制造的发展&#xff0c;对设备状态实时监控和数据采集提出了更高要求。本文提出了一种基于YOLO的工业表计读数识别方法&#xff0c;通过首先利用YOLO进行表计目标检测&#xff0c;提取出单独的表计图像&#xff0c;然后分别对表针和刻度进行关键点检测&…...

Redis--Zset类型

目录 一、引言 二、介绍 三、命令 1.zadd 2.zrange&#xff0c;zrevrange&#xff0c;zrangebyscore 3.zcard&#xff0c;zcount 4.zpopmax&#xff0c;bzpopmax&#xff0c;zpopmin&#xff0c;bzpopmin 5.zrank,zrevrank,zscore 6.zrem&#xff0c;zremrangebyrank&a…...

Java 大视界 -- 基于 Java 的大数据机器学习模型的迁移学习应用与实践(129)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

SpringBoot 第一课(Ⅲ) 配置类注解

目录 一、PropertySource 二、ImportResource ①SpringConfig &#xff08;Spring框架全注解&#xff09; ②ImportResource注解实现 三、Bean 四、多配置文件 多Profile文件的使用 文件命名约定&#xff1a; 激活Profile&#xff1a; YAML文件支持多文档块&#xff…...

期望最大化(EM)算法

MLE &#xff08;最大似然估计&#xff09;是一种非常有效的参数估计方法&#xff0c;但当分布中有多余参数或数据为截尾或缺失时&#xff0c;其 MLE 的求取是比较困难的。于是 Dempster 等人于 1977 年提出了 EM 算法&#xff0c;其出发点是把求 MLE 的过程分两步走&#xff1…...

DeepSeek与人工智能:技术演进、架构解析与未来展望

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 1. DeepSeek技术全景解析1.1 DeepSeek技术定位1.2 核心技术组件 2. 人工智能发展路线2.1 技术…...

Keepalived 多主模型与 LVS 高可用

一.Keepalived多主模型 Keepalived多主模型概念 如上图&#xff0c;keepalived主从架构性能损耗较严重&#xff0c;如果业务分类明确&#xff0c;则可以配置keepalived多主模型降低损耗&#xff0c;两台keepalived互为主备&#xff0c;如&#xff1a;订单业务走keepalived1&am…...

AGI大模型(6):提示词模型进阶

1 零样本提示 如今,经过⼤量数据训练并调整指令的LLM能够执⾏零样本任务。 代码如下: from openai import OpenAI from dotenv import load_dotenv load_dotenv() # 初始化 OpenAI 服务。 client = OpenAI()prompt = """ 将⽂本分类为中性、负⾯或正⾯。 ⽂…...

群体智能优化算法-旗鱼优化算法 (Sailfish Optimizer, SFO,含Matlab源代码)

摘要 旗鱼优化算法&#xff08;Sailfish Optimizer, SFO&#xff09;是一种模拟旗鱼&#xff08;Sailfish&#xff09;和沙丁鱼&#xff08;Sardine&#xff09;之间捕食关系的新型元启发式算法。通过在搜索过程中模拟旗鱼对沙丁鱼的捕食行为&#xff0c;以及沙丁鱼群的逃逸与…...

适合企业内训的AI工具实操培训教程(37页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;适合企业内训的 AI 工具实操培训教程 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;技术迅速发展&#xff0c;深度融入到各个领域&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;更是成…...

用 Python 进行比特币数据分析:从入门到实战

用 Python 进行比特币数据分析:从入门到实战 前言 比特币,这个“数字黄金”,已经成为全球金融市场不可忽视的存在。无论是短线交易、长期投资,还是链上数据分析,都离不开数据的支撑。而 Python,作为数据分析的瑞士军刀,为我们提供了一整套强大的工具。 本篇文章将带你…...

CT重建笔记(四)——三维重建

人如果不思考不学习&#xff0c;天天刷短视频&#xff0c;跟咸鱼有什么区别&#xff1f; 平行的线积分数据&#xff08;X射线变换&#xff09; 平行光束图像重建的理论基础是中心切片定理&#xff08;二维情形见我的博客https://leslielee.blog.csdn.net/article/details/134…...