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

RabbitMQ高级特性2

RabbitMQ高级特性2

  • 一.TTL
    • 1.设置消息的TTL
    • 2.设置队列的过期时间
  • 二.死信队列
    • 1.死信
    • 2.代码实现
    • 3.消息被拒绝的死信
    • 超出队列长度时的死信
    • 死信队列的应用场景
  • 三.延迟队列
    • 1.概念
    • 2.应用场景
    • 3.代码实现
        • 延迟队列插件安装和配置
        • 代码
    • 4.总结
  • 四.事务
    • 1.未采用事务
    • 2.采用事务
  • 五.消息分发
    • 1.概念和解决方法
    • 2.应用场景
    • 3.限流实现
    • 4.负载均衡

一.TTL

RabbitMQ可以对队列和消息设置TTL(过期时间),当消息存活的时间超过了TTL,此时消息及时没有被消费也会自动删除,队列也是一样的。

需要注意的是,在队列和消息都设置了过期时间后,会根据最短的过期时间来进行删除消息或者队列,如果队列删除了,消息自然也就没有了。

如果此时发送了两条消息,第一条消息过期时间为10秒,第二条消息过期时间为5秒,此时先等待的是第一条消息,当第一条消息过期了,第二条消息才会过期。

因为此时第二条消息已经在队列中存在的时间超过了TTL设置的时间,当第一条消息过期时,第二条消息就会称为队列头部,检查时,则满足了TTL的过期时间,则直接出队,二者并不会互相影响。

个人理解:他们等待时间是共享的,意思就是当第一条消息等待了10秒,未被消费者消费,并且与此同时第二条消息也没有被消费,此时第一条消息过期被删除,第二条也会直接被过期删除,而不会在等待5秒的时间。

1.设置消息的TTL

Configuration

//过期时间@Bean("ttlQueue")public Queue ttlQueue() {return QueueBuilder.durable(Constants.TTL_QUEUE).build();}@Bean("ttlExchange")public DirectExchange ttlExchange() {return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).build();}@Bean("ttlBinding")public Binding ttlBinding(@Qualifier("ttlQueue") Queue queue , @Qualifier("ttlExchange") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("ttl");}

Producer

@RequestMapping("/ttl")public String ttl() {//设置过期时间MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setExpiration("10000");//毫秒return message;}};rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","ttl test...",messagePostProcessor);return "ttl is ok!";}

2.设置队列的过期时间

Configuration

//设置过期队列@Bean("ttlQueue2")public Queue ttlQueue2() {return QueueBuilder.durable(Constants.TTL_QUEUE2).ttl(20000).build();}@Bean("ttlExchange2")public DirectExchange ttlExchange2() {return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).build();}@Bean("ttlBinding2")public Binding ttlBinding2(@Qualifier("ttlQueue2") Queue queue , @Qualifier("ttlExchange2") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("ttl");}

Producer

@RequestMapping("/ttl2")public String ttl2() {rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","ttl2 test...");return "ttl2 is ok!";}

二.死信队列

1.死信

死信的概念:

死信(dead message)简单理解就是因为种种原因,无法被消费的信息,就是死信。有死信,自然就有死信队列。

当消息在⼀个队列中变成死信之后,它能被重新被发送到另⼀个交换器中,这个交换器就是DLX( Dead Letter Exchange ),绑定DLX的队列,就称为死信队列(Dead Letter Queue,简称DLQ)。

在这里插入图片描述

死信的原因

  1. 消息被拒绝( Basic.Reject/Basic.Nack ),并且设置 requeue 参数为false。
    原因:消息在队列中存活的时间超过了设定的TTL
  2. 消息过期。
    原因:消费者在处理消息时,可能因为消息内容错误,处理逻辑异常等原因拒绝处理该消息。如果拒绝时指定不重新入队(requeue=false),消息也会成为死信.
  3. 队列达到最大长度。
    原因:当队列达到最大长度,无法再容纳新的消息时,新来的消息会被处理为死信

2.代码实现

DLConfiguration

package com.example.rabbitmqdemo.config;import com.example.rabbitmqdemo.constant.Constants;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DLconfig {//正常的交换机和队列@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx").ttl(10000).build();}@Bean("normalExchange")public DirectExchange normalExchange() {return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).build();}@Bean("/normalBinding")public Binding normalBinding(@Qualifier("normalQueue") Queue queuem, @Qualifier("normalExchange") Exchange exchange) {return BindingBuilder.bind(queuem).to(exchange).with("normal").noargs();}//死信交换机和队列@Bean("dlQueue")public Queue dlQueue() {return QueueBuilder.durable(Constants.DL_QUEUE).build();}@Bean("dlExchange")public DirectExchange dlExchange() {return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).build();}@Bean("/dlBinding")public Binding dlBinding(@Qualifier("dlQueue") Queue queuem, @Qualifier("dlExchange") DirectExchange exchange) {return BindingBuilder.bind(queuem).to(exchange).with("dlx");}
}

Producer

@RequestMapping("/dl")public String dl() {rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","normal test...");return "dl test!";}

3.消息被拒绝的死信

DLListener

package com.example.rabbitmqdemo.listener;import com.example.rabbitmqdemo.constant.Constants;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.io.UnsupportedEncodingException;@Component
public class DLListener {@RabbitListener(queues = Constants.NORMAL_QUEUE)public void handleMessage(Message message, Channel channel) throws IOException {long deliveryTag = message.getMessageProperties().getDeliveryTag();try {System.out.printf("接收到消息: %s ,deliveryTag: %d \n",new String(message.getBody(),"UTF-8"),deliveryTag);System.out.println("业务逻辑处理");int num = 3 / 0;System.out.println("业务逻辑处理完成");//肯定确认channel.basicAck(deliveryTag,false);}catch (Exception e) {//否定确认channel.basicNack(deliveryTag,false,false);//requeue为false,则为死信}}@RabbitListener(queues = Constants.DL_QUEUE)public void handleMessage2(Message message, Channel channel) throws IOException {long deliveryTag = message.getMessageProperties().getDeliveryTag();System.out.printf("接收到消息: %s ,deliveryTag: %d \n", new String(message.getBody(), "UTF-8"), deliveryTag);}}

超出队列长度时的死信

Configuration

package com.example.rabbitmqdemo.config;import com.example.rabbitmqdemo.constant.Constants;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DLconfig {//正常的交换机和队列@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx").maxLength(10).ttl(10000).build();}@Bean("normalExchange")public DirectExchange normalExchange() {return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).build();}@Bean("/normalBinding")public Binding normalBinding(@Qualifier("normalQueue") Queue queuem, @Qualifier("normalExchange") Exchange exchange) {return BindingBuilder.bind(queuem).to(exchange).with("normal").noargs();}//死信交换机和队列@Bean("dlQueue")public Queue dlQueue() {return QueueBuilder.durable(Constants.DL_QUEUE).build();}@Bean("dlExchange")public DirectExchange dlExchange() {return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).build();}@Bean("/dlBinding")public Binding dlBinding(@Qualifier("dlQueue") Queue queuem, @Qualifier("dlExchange") DirectExchange exchange) {return BindingBuilder.bind(queuem).to(exchange).with("dlx");}
}

** Producer**

@RequestMapping("/dl")public String dl() {for (int i = 0; i < 20; i++) {rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","normal test... " + i);}return "dl test!";}

死信队列的应用场景

对于RabbitMQ来说,死信队列是⼀个非常有用的特性。它可以处理异常情况下,消息不能够被消费者正确消费而被置入死信队列中的情况,应用程序可以通过消费这个死信队列中的内容来分析当时所遇到的异常情况,进而可以改善和优化系统。

比如:用户支付订单之后,支付系统会给订单系统返回当前订单的支付状态为了保证支付信息不丢失,需要使用到死信队列机制。当消息消费异常时,将消息投入到死信队列中,由订单系统的其他消费者来监听这个队列,并对数据进行处理(比如发送工单等,进行人工确认)

场景的应用场景还有:

  • 消息重试:将死信消息重新发送到原队列或另⼀个队列进行重试处理

  • 消息丢弃:直接丢弃这些无法处理的消息,以避免它们占用系统资源

  • 日志收集:将死信消息作为日志收集起来,用于后续分析和问题定位

三.延迟队列

1.概念

延迟队列(Delayed Queue),即消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。

RabbitMQ本身没有直接支持延迟队列的的功能,但是可以通过前面所介绍的TTL+死信队列的方式组合模拟出延迟队列的功能。

在这里插入图片描述

2.应用场景

  1. 智能家居:用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作。这时候就可以将用户指令发送到延迟队列,当指令设定的时间到了再将指令推送到智能设备。
  2. 日常管理:预定会议后,需要在会议开始前十五分钟提醒参会人参加会议
  3. 用户注册成功后,7天后发送短信,提高用户活跃度等

3.代码实现

在实现死信队列的代码中将监听的消费者的队列设置为DL的队列即可,不在监听normal的队列,再将normal的队列设置TTL后,就是所谓的延迟队列实现。

但是如果是消息有TTL的话,如果处于队头的消息是30秒过期,在队头之后的元素是10秒过期,则当30秒的消息过期之后,10秒的消息也直接过期了,此时两条消息就会一起出来,此时就不是我们所预想的结果了

延迟队列插件安装和配置

此时解决这个办法可以使用一个延迟队列的插件,点击此处就可以跳转插件连接的下载地址

下载这个ez后缀的文件即可

在这里插入图片描述

在这里插入图片描述

在云服务器上进入这个路径后在进行安装插件:

在这里插入图片描述
在这里插入图片描述

再将下载好后的文件拖入到云服务器中进行安装:
在这里插入图片描述
在通过命令(rabbitmq-plugins list)查看插件是否安装成功:
还需要注意下载插件的版本要和云服务器上安装的版本相近,差距太远是无法启动这个插件的。
在这里插入图片描述

(rabbitmq-plugins enable rabbitmq_delayed_message_exchange)
通过这个命令启动插件

成功后会有红色框的提示:

在这里插入图片描述
成功之后最好重启RabbitMQ的服务器(service rabbitmq-server restart)
成功后在RabbitMQ的管理页面中会有红色框的选择:
在这里插入图片描述

停止插件的命令
rabbitmq-plugins disable rabbitmq_delayed_message_exchange:

上述安装插件的路径还可以选择其他路径,这里就不再赘述了,安装的方式都是大同小异的。

这样就能够解决了消息TTL不同而导致消息出队问题。

代码

Producer

@RequestMapping("/delay2")public String delay2() {MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setDelayLong(30000L);return message;}};rabbitTemplate.convertAndSend(Constants.DELAY_EXCHANGE,"delay","delay test is running...",messagePostProcessor);MessagePostProcessor messagePostProcessor2 = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setDelayLong(10000L);return message;}};rabbitTemplate.convertAndSend(Constants.DELAY_EXCHANGE,"delay","delay test is running...",messagePostProcessor2);System.out.printf("%tc 消息发送成功 \n",new Date());return "delay2 is ok!";}

Configuration

@Configuration
public class DelayConfiguration {@Bean("delayQueue")public Queue delayQueue() {return QueueBuilder.durable(Constants.DELAY_QUEUE).build();}@Bean("delayExchange")public Exchange delayExchange() {return ExchangeBuilder.directExchange(Constants.DELAY_EXCHANGE).delayed().build();}@Bean("delayBinding")public Binding delayBinding(@Qualifier("delayQueue") Queue queue, @Qualifier("delayExchange") Exchange exchange) {return BindingBuilder.bind(queue).to(delayExchange()).with("delay").noargs();}
}

Listener

@Component
public class DelayListener {@RabbitListener(queues = Constants.DELAY_QUEUE)public void delayHandMessage(Message message, Channel channel) throws UnsupportedEncodingException {System.out.printf("%tc delay接受 \n",new Date());System.out.printf("接收到消息 %s\n",new String(message.getBody(),"UTF-8"));}
}

4.总结

RabbitMQ本⾝并没直接实现延迟队列,通常有两种方法:

  1. TTL+死信队列组合的方式
  2. 使用官方提供的延迟插件实现延迟功能

⼆者对比:

  1. 基于死信实现的延迟队列
    a. 优点:
    1)灵活不需要额外的插件支持
    b. 缺点:
    1)存在消息顺序问题
    2)需要额外的逻辑来处理死信队列的消息,增加了系统的复杂性

  2. 基于插件实现的延迟队列
    a. 优点:
    1)通过插件可以直接创建延迟队列,简化延迟消息的实现.
    2)避免了DLX的时序问题
    b. 缺点:
    1)需要依赖特定的插件,有运维⼯作
    2)只适用特定版本

四.事务

RabbitMQ是基于AMQP协议实现的,该协议实现了事务机制。因此RabbitMQ也⽀持事务机制,Spring AMQP也提供了对事务相关的操作。RabbitMQ事务允许开发者确保消息的发送和接收是原子性的,要么全部成功,要么全部失败。

1.未采用事务

如果不采用事务,第一条消息发送成功,第二条消息发送失败:

Producer

 @RequestMapping("/trans")public String trans() {System.out.println("事务测试");//使用内置交换机rabbitTemplate.convertAndSend("",Constants.TRANS_QUEUE,"trans test1....");int sum = 3 / 0;rabbitTemplate.convertAndSend("",Constants.TRANS_QUEUE,"trans test2....");return "trans is ok!";}

Configuration

@Configuration
public class TransConfig {@Bean("transQueue")public Queue transQueue() {return QueueBuilder.durable(Constants.TRANS_QUEUE).build();}
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.采用事务

因为事务发送失败,应该一条都不发送,所以需要按照下面的方式进行写代码:

为了不让所有使用RabbitTemplate的其他方法也启动事务,所以单独写一个方法交给Spring进行管理:

RabbitTemplate

package com.example.rabbitmqdemo.config;import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitTemplateConfig {@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);return rabbitTemplate;}@Beanpublic RabbitTemplate confirmRabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);//设置回调函数rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {System.out.println("执行了confirm方法");if (ack) {System.out.printf("接收到消息, 消息ID: %s \n",correlationData == null ? null : correlationData.getId());}else {System.out.printf("未接收到消息, 消息ID: %s, cause: %s \n",correlationData == null ? null : correlationData.getId(),cause);//相应的业务处理}}});//return模式rabbitTemplate.setMandatory(true);rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {@Overridepublic void returnedMessage(ReturnedMessage returnedMessage) {System.out.println("消息退回: " + returnedMessage);}});return rabbitTemplate;}@Bean("transRabbitTemplate")public RabbitTemplate transRabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setChannelTransacted(true);//开启事务return rabbitTemplate;}@Beanpublic RabbitTransactionManager rabbitTransactionManager(ConnectionFactory connectionFactory) {return new RabbitTransactionManager(connectionFactory);}}

Producer

@Resource(name = "transRabbitTemplate")private RabbitTemplate transRabbitTemplate;@Transactional@RequestMapping("/trans2")public String trans2() {System.out.println("事务测试");//使用内置交换机transRabbitTemplate.convertAndSend("",Constants.TRANS_QUEUE,"trans test1....");int sum = 3 / 0;transRabbitTemplate.convertAndSend("",Constants.TRANS_QUEUE,"trans test2....");return "trans is ok!";}

Configuration

@Configuration
public class TransConfig {@Bean("transQueue")public Queue transQueue() {return QueueBuilder.durable(Constants.TRANS_QUEUE).build();}
}

五.消息分发

1.概念和解决方法

概念

RabbitMQ队列拥有多个消费者时,队列会把收到的消息分派给不同的消费者。每条消息只会发送给订阅列表里的⼀个消费者。这种方式非常适合扩展。如果现在负载加重,那么只需要创建更多的消费者来消费处理消息即可。

默认情况下,RabbitMQ是以轮询的方法进行分发的,而不管消费者是否已经消费并已经确认了消息。这种方式是不太合理的。试想⼀下,如果某些消费者消费速度慢,而某些消费者消费速度快,就可能会导致某些消费者消息积压,某些消费者空闲,进而应用整体的吞吐量下降。

解决方法
可以使用前面章节讲到的channel.basicQos(int prefetchCount)方法,来限制当前信道上的消费者所能保持的最大未确认消息的数量。

比如:消费端调⽤了channelbasicQos(5),RabbitMQ会为该消费者计数,发送⼀条消息计数+1,消费⼀条消息计数-1,当达到了设定的上限,RabbitMQ就不会再向它发送消息了,直到消费者确认了某条消息.类似TCP/IP中的"滑动窗".

2.应用场景

  1. 限流
  2. ⾮公平分发

3.限流实现

未将确认消息启动,启动后就是限流模式

配置yml

#ack 确认方式:开启ack
listener:simple:acknowledge-mode: manual #⼿动确认prefetch: 5

Producer

@RequestMapping("/qos")public String qos() {for (int i = 0; i < 20; i++) {rabbitTemplate.convertAndSend(Constants.QOS_EXCHANGE,"qos","qos test...." + i);}return "trans is ok!";}

Configuration

@Configuration
public class QosConfiguration {@Bean("qosQueue")public Queue qosQueue() {return QueueBuilder.durable(Constants.QOS_QUEUE).build();}@Bean("qosExchange")public Exchange qosExchange() {return ExchangeBuilder.directExchange(Constants.QOS_EXCHANGE).build();}@Bean("qosBinding")public Binding qosBinding(@Qualifier("qosQueue") Queue queue, @Qualifier("qosExchange") Exchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("qos").noargs();}
}

Listener

@Component
public class QosListener {@RabbitListener(queues = Constants.QOS_QUEUE)public void handleMessage(Message message, Channel channel) throws IOException {try {System.out.printf("接收到消息: %s , deliveryTag: %d \n",new String(message.getBody(),"UTF-8"),message.getMessageProperties().getDeliveryTag());//确认消息(肯定)//如果没有启动确认消息则会有下图的情况            //channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}catch (Exception e) {//否定确认//最后一个参数为true,则发生异常重新入队,false,为不再入队channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);}}}

在这里插入图片描述
在这里插入图片描述

4.负载均衡

代码实现:
其余都和限流模式相同

Listener

@Component
public class QosListener {@RabbitListener(queues = Constants.QOS_QUEUE)public void handleMessage(Message message, Channel channel) throws IOException {try {System.out.printf("111接收到消息: %s , deliveryTag: %d \n",new String(message.getBody(),"UTF-8"),message.getMessageProperties().getDeliveryTag());//模拟业务处理的时间Thread.sleep(2000);//确认消息(肯定)channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}catch (Exception e) {//否定确认//最后一个参数为true,则发生异常重新入队,false,为不再入队channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);}}@RabbitListener(queues = Constants.QOS_QUEUE)public void handleMessage2(Message message, Channel channel) throws IOException {try {System.out.printf("222接收到消息: %s , deliveryTag: %d \n",new String(message.getBody(),"UTF-8"),message.getMessageProperties().getDeliveryTag());//模拟业务处理的时间Thread.sleep(1000);//确认消息(肯定)channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}catch (Exception e) {//否定确认//最后一个参数为true,则发生异常重新入队,false,为不再入队channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);}

在这里插入图片描述

相关文章:

RabbitMQ高级特性2

RabbitMQ高级特性2 一.TTL1.设置消息的TTL2.设置队列的过期时间 二.死信队列1.死信2.代码实现3.消息被拒绝的死信超出队列长度时的死信死信队列的应用场景 三.延迟队列1.概念2.应用场景3.代码实现延迟队列插件安装和配置代码 4.总结 四.事务1.未采用事务2.采用事务 五.消息分发…...

基于FPGA的特定序列检测器verilog实现,包含testbench和开发板硬件测试

目录 1.课题概述 2.系统测试效果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 本课题采用基于伪码匹配相关峰检测的方式实现基于FPGA的特定序列检测器verilog实现,包含testbench和开发板硬件测试。 2.系统测试效果 仿真测试 当检测到序列的时候&#xf…...

【大数据知识】Flink分布式流处理和批处理框架

Flink分布式流处理和批处理框架 概述Flink入门介绍**1. Flink是什么&#xff1f;****2. 核心特性****3. 核心组件****4. 应用场景** Flink底层实现原理详细说明**1. 分布式架构****2. 流处理模型****3. 状态管理****4. 容错机制****5. 网络通信与数据传输****6. 资源管理与扩展…...

Java面试黄金宝典33

1. 什么是存取控制、 触发器、 存储过程 、 游标 存取控制 定义&#xff1a;存取控制是数据库管理系统&#xff08;DBMS&#xff09;为保障数据安全性与完整性&#xff0c;对不同用户访问数据库对象&#xff08;如表、视图等&#xff09;的权限加以管理的机制。它借助定义用户…...

实战解析:基于AWS Serverless架构的高并发微服务设计与优化

随着云计算进入深水区&#xff0c;Serverless架构正在重塑现代微服务的设计范式。本文将以电商秒杀系统为场景&#xff0c;基于AWS Serverless服务构建高可用架构&#xff0c;并深入探讨性能优化方案。 一、架构设计解析 我们采用分层架构设计&#xff0c;核心组件包括&#…...

Muduo网络库介绍

1.Reactor介绍 1.回调函数 **回调&#xff08;Callback&#xff09;**是一种编程技术&#xff0c;允许将一个函数作为参数传递给另一个函数&#xff0c;并在适当的时候调用该函数 1.工作原理 定义回调函数 注册回调函数 触发回调 2.优点 异步编程 回调函数允许在事件发生时…...

Cribl 导入文件来检查pipeline 的设定规则(eval 等)

Cribl 导入文件来检查pipeline 的设定规则(eval 等) 从这个页面先下载,或者copy 内容来创建pipeline: Reducing Windows XML Events | Cribl Docs...

2360. 图中的最长环

2360. 图中的最长环 题目链接&#xff1a;2360. 图中的最长环 代码如下&#xff1a; //参考链接&#xff1a;https://leetcode.cn/problems/longest-cycle-in-a-graph/solutions/1710828/nei-xiang-ji-huan-shu-zhao-huan-li-yong-pmqmr class Solution { public:int longest…...

深度学习入门(三):神经网络的学习

文章目录 前言人类思考 VS 机器学习 VS 深度学习基础术语损失函数常用的损失函数均方误差MSE&#xff08;Mean Square Error&#xff09;交叉熵误差&#xff08;Cross Entropy Error&#xff09;mini-batch学习 为何要设定损失函数数值微分神经网络学习算法的实现两层神经网络的…...

Python 推导式:简洁高效的数据生成方式

为什么需要推导式&#xff1f; 在Python编程中&#xff0c;我们经常需要对数据进行各种转换和过滤操作。传统的方法是使用循环结构&#xff0c;但这往往会导致代码冗长且不够直观。Python推导式&#xff08;Comprehensions&#xff09;应运而生&#xff0c;它提供了一种简洁、…...

HTML5+CSS3+JS小实例:带滑动指示器的导航图标

实例:带滑动指示器的导航图标 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, ini…...

一周学会Pandas2 Python数据处理与分析-Jupyter Notebook安装

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili Jupyter (Project Jupyter | Home&#xff09;项目是一个非营利性开源项目&#xff0c;于2014年由IPython项目中诞生…...

FPGA状态机思想实现流水灯及HDLBits学习

目录 第一章 在DE2-115上用状态机思想实现LED流水灯1.1 状态机设计思路1.2 Verilog代码实现1.3. 仿真测试代码1.4 编译代码与仿真 第二章 CPLD和FPGA芯片的主要技术区别是什么&#xff1f;它们各适用于什么场合&#xff1f;2.1 主要技术区别2.2 适用场合 第三章 HDLBits学习3.1…...

【教程】Windows下 Xshell 连接跳板机和开发机

需求 使用远程连接工具 Xshell 连接跳板机&#xff0c;再从跳板机连接开发机&#xff0c;用户登陆方式为使用密钥。 方法 首先&#xff0c;建立一个会话&#xff0c;用于配置跳板机信息和开发机转跳信息&#xff1a; 在【连接】页面&#xff0c;给跳板机取个名字&#xff0c…...

Java导出excel,表格插入pdf附件,以及实现过程中遇见的坑

1.不能使用XSSFWorkbook,必须使用HSSFWorkbook,否则导出excel后&#xff0c;不显示插入的图标和内容&#xff0c;如果是读取的已有的excel模板&#xff0c;必须保证excel的格式是xls&#xff0c;如果把xlsx通过重命名的方式改为xls&#xff0c;是不生效的&#xff0c;后面执行下…...

神马系统8.5搭建过程,附源码数据库

项目介绍 神马系统是多年来流行的一款电视端应用&#xff0c;历经多年的发展&#xff0c;在稳定性和易用性方面都比较友好。 十多年前当家里的第一台智能电视买回家&#xff0c;就泡在某论坛&#xff0c;找了很多APP安装在电视上&#xff0c;其中这个神马系统就是用得很久的一…...

cesium 材质 与 交互 以及 性能相关介绍

文章目录 cesium 材质 与 交互 以及 性能相关介绍1. Cesium 材质与着色器简介2. 具体实例应用核心代码及解释3. 代码解释 Cesium 交互1. 常见交互和事件类型2. 示例代码及解释3. 代码解释 cesium 性能优化数据加载与管理渲染优化相机与场景管理代码优化服务器端优化 案例分享1.…...

指令补充+样式绑定+计算属性+监听器

一、指令补充 1. 指令修饰符 1. 作用: 借助指令修饰符, 可以让指令更加强大 2. 分类: 1> 按键修饰符: 用来检测用户的按键, 配合键盘事件使用. keydown 和 keyup 语法: keydown.enter/v-on:keydown.enter 表示当enter按下的时候触发 keyup.enter/v-on:keyup.enter 表示当…...

基于Android的病虫害防治技术系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 基于Android的病虫害防治技术系统设计的目的是为用户提供一个病虫害防治技术管理的平台。与PC端应用程序相比&#xff0c;病虫害防治技术管理的设计主要面向于广大用户&#xff0c;旨在为用户提供一个查看科普内容&#xff0c;进行病虫识别、发帖交流的平台。 基于Androi…...

ffmpeg 使用不同编码器编码hevc的速度

1.核显uhd630 编码器hevc_qsv ffmpeg版本2024-03-14 2.73X 转码完成后大小 971mb 2.1680V4 编码器 libx265 ffmpeg版本2025-05-07 1.42x 转码完成后大小 176mb 3.RX588 编码器hevc_amf ffmpeg版本2024-03-14 转码完成后大小 376MB 4.1680v4dg1rx584 编码器hevc_amf ffm…...

【硬件模块】数码管模块

一位数码管 共阳极数码管&#xff1a;8个LED共用一个阳极 数字编码00xC010xF920xA430xB040x9950x9260x8270xF880x8090x90A0x88B0x83C0xC6D0xA1E0x86F0x8E 共阴极数码管&#xff1a;8个LED共用一个阴极 数字编码00x3F10x0620x5B30x4F40x6650x6D60x7D70x0780x7F90x6FA0x77B0x7…...

NO.64十六届蓝桥杯备战|基础算法-简单贪心|货仓选址|最大子段和|纪念品分组|排座椅|矩阵消除(C++)

贪⼼算法是两极分化很严重的算法。简单的问题会让你觉得理所应当&#xff0c;难⼀点的问题会让你怀疑⼈⽣ 什么是贪⼼算法&#xff1f; 贪⼼算法&#xff0c;或者说是贪⼼策略&#xff1a;企图⽤局部最优找出全局最优。 把解决问题的过程分成若⼲步&#xff1b;解决每⼀步时…...

ubuntu22.04LTS设置中文输入法

打开搜狗网址直接下载软件&#xff0c;软件下载完成后&#xff0c;会弹出安装教程说明书。 网址:搜狗输入法linux-首页搜狗输入法for linux—支持全拼、简拼、模糊音、云输入、皮肤、中英混输https://shurufa.sogou.com/linux...

基于YOLOv8的热力图生成与可视化-支持自定义模型与置信度阈值的多维度分析

目标检测是计算机视觉领域的重要研究方向&#xff0c;而YOLO&#xff08;You Only Look Once&#xff09;系列算法因其高效性和准确性成为该领域的代表性方法。YOLOv8作为YOLO系列的最新版本&#xff0c;在目标检测任务中表现出色。然而&#xff0c;传统的目标检测结果通常以边…...

常见设计系统清单

机构设计系统toB/toC网站GoogleMaterial DesignCm3.material.ioIBM CarbonDesign SystemBcarbondesignsystem.comSalesforceLightning Design SystemBlightningdesignsystem.comMicrosoftFluent Design SystemCfluent2.microsoft.design阿里Ant DesignCant.designSAPFiori Desi…...

React编程高级主题:错误处理(Error Handling)

文章目录 **5.2 错误处理&#xff08;Error Handling&#xff09;概述****5.2.1 onErrorReturn / onErrorResume&#xff08;错误回退&#xff09;****1. onErrorReturn&#xff1a;提供默认值****2. onErrorResume&#xff1a;切换备用数据流** **5.2.2 retry / retryWhen&…...

【设计模式】代理模式

简介 假设你在网上购物时&#xff0c;快递员无法直接将包裹送到你手中&#xff08;比如你不在家&#xff09;。 代理模式的解决方案是&#xff1a; 快递员将包裹交给小区代收点&#xff08;代理&#xff09;&#xff0c;代收点代替你控制和管理包裹的访问。 代收点可以添加额外…...

局域网:电脑或移动设备作为主机实现局域网访问

电脑作为主机 1. 启用电脑的网络发现、SMB功能 2. 将访问设备开启WIFI或热点&#xff0c;用此电脑连接&#xff1b;或多台设备连接到同一WIFI 3. 此电脑打开命令行窗口&#xff0c;查看电脑本地的IP地址 Win系统&#xff1a;输入"ipconfig"&#xff0c;回车后如图 4.…...

图论的基础

E - Replace&#xff08;判环&#xff0c;破环成链&#xff09; #include <bits/stdc.h> #include <atcoder/dsu>using namespace std; using namespace atcoder;const int C 26;int main() {int n;cin >> n;string s, t;cin >> s >> t;if (s …...

Jetpack Compose CompositionLocal 深入解析:局部参数透传实践

Jetpack Compose CompositionLocal 深入解析&#xff1a;局部参数透传实践 在 Jetpack Compose 中&#xff0c;如何优雅地在组件之间传递数据&#xff0c;而不需要层层传参&#xff1f; CompositionLocal 就是为了解决这个问题的&#xff01; 1. 什么是 CompositionLocal&#…...

第十五届蓝桥杯大赛软件赛省赛Python 大学 C 组:3.数字诗意

题目1 数字诗意 在诗人的眼中&#xff0c;数字是生活的韵律&#xff0c;也是诗意的表达。 小蓝&#xff0c;当代顶级诗人与数学家&#xff0c;被赋予了”数学诗人”的美誉。他擅长将冰冷的数字与抽象的诗意相融合&#xff0c;并用优雅的文字将数学之美展现于纸上。 某日&…...

Oracle数据库数据编程SQL<8 文本编辑器Notepad++和UltraEdit(UE)对比>

首先&#xff0c;用户界面方面。Notepad是开源的&#xff0c;界面看起来比较简洁&#xff0c;可能更适合喜欢轻量级工具的用户。而UltraEdit作为商业软件&#xff0c;界面可能更现代化&#xff0c;功能布局更复杂一些。不过&#xff0c;UltraEdit支持更多的主题和自定义选项&am…...

P12013 [Ynoi April Fool‘s Round 2025] 牢夸 Solution

Description 给定序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1​,a2​,⋯,an​)&#xff0c;有 m m m 个操作分两种&#xff1a; add ⁡ ( l , r , k ) \operatorname{add}(l,r,k) add(l,r,k)&#xff1a;对每个 i ∈ [ l , r ] i\in[l,r] i∈[l,r] 执行 …...

PostgreSQL LIKE 操作符详解

PostgreSQL LIKE 操作符详解 引言 在数据库查询中,LIKE 操作符是一种非常常用的字符串匹配工具。它可以帮助我们实现模糊查询,从而提高查询的灵活性。本文将详细介绍 PostgreSQL 中的 LIKE 操作符,包括其语法、使用方法以及一些注意事项。 LIKE 操作符语法 LIKE 操作符通…...

【前端】【Nuxt3】Nuxt3的生命周期

路由导航和中间件执行顺序 路由导航开始 中间件执行顺序&#xff1a; 全局中间件&#xff08;middleware/*.global.js&#xff09;布局中间件&#xff08;在definePageMeta中定义的布局级中间件&#xff09;页面中间件&#xff08;在definePageMeta中定义的页面级中间件&#…...

热更新简介+xLua基础调用

什么是冷更新 开发者将测试好的代码&#xff0c;发布到应用商店的审核平台&#xff0c;平台方会进行稳定性及性能测试。测试成功后&#xff0c;用户即可在AppStore看到应用的更新信息&#xff0c;用户点击应用更新后&#xff0c;需要先关闭应用&#xff0c;再进行更新。 什么是…...

大钲资本押注儒拉玛特全球业务,累计交付超2500条自动化生产线儒拉玛特有望重整雄风,我以为它破产倒闭了,担心很多非标兄弟们失业

1. 交易概况 时间与主体:大钲资本于2025年4月1日正式宣布完成对儒拉玛特自动化技术(苏州)有限公司及其全球子公司和关联企业的收购。交易通过大钲资本旗下美元基金设立的儒拉玛特(新加坡)公司作为控股主体进行,交易金额未披露。 收购范围:包括儒拉玛特亚太、欧洲、北美等…...

FPGA系统开发板调试过程不同芯片的移植步骤介绍

目录 1.我目前使用的开发板 2.不同开发板的移植 步骤一&#xff1a;芯片型号设置 步骤二&#xff1a;约束修改 步骤三、IP核更新 关于FPGA系统开发板调试过程中不同芯片的移植。我需要先理清楚FPGA开发中移植到不同芯片的一般流程。首先&#xff0c;移植通常涉及到更换FPG…...

算法设计与分析5(动态规划)

动态规划的基本思想 将一个问题划分为多个不独立的子问题&#xff0c;这些子问题在求解过程中可能会有些数据进行了重复计算。我们可以把计算过的数据保存起来&#xff0c;当下次遇到同样的数据计算时&#xff0c;就可以查表直接得到答案&#xff0c;而不是再次计算 动态规划…...

ModuleNotFoundError: No module named ‘matplotlib_inline‘

ModuleNotFoundError: No module named matplotlib_inline 1. ModuleNotFoundError: No module named matplotlib_inline2. matplotlib-inlineReferences 如果你在普通的 Python 脚本或命令行中运行代码&#xff0c;那么不需要 matplotlib_inline&#xff0c;因为普通的 Python…...

Mysql 中的 B+树 和 B 树在进行数据增删改查后的结构调整过程是怎样的?

B 树的增、删、改、查数据的调整过程 在 MySQL 中&#xff0c;B 树 是一种广泛用于存储引擎&#xff08;如 InnoDB&#xff09;中的索引结构。B 树的结构使得它非常适合于处理大量数据的插入、删除和查询等操作。B 树是一种自平衡的树数据结构&#xff0c;其中所有的值都存储在…...

在Rust生态中探索高性能HTTP服务器:Hyperlane初体验

在Rust生态中探索高性能HTTP服务器&#xff1a;Hyperlane初体验 最近在调研Rust的HTTP服务器方案时&#xff0c;发现了一个有趣的新项目——Hyperlane。这个轻量级库宣称在保持简洁API的同时&#xff0c;性能表现可圈可点。作为Rust生态的长期观察者&#xff0c;我决定深入体验…...

AI医疗诊疗系统设计方案

AI医疗诊疗系统设计方案 1. 项目概述 1.1 项目背景 随着人工智能技术的快速发展&#xff0c;将AI技术应用于医疗诊疗领域已成为提升医疗服务效率和质量的重要途径。本系统旨在通过AI技术辅助医生进行诊疗服务&#xff0c;提供智能化的医疗决策支持。 1.2 项目目标 提供全面…...

k8s的StorageClass存储类和pv、pvc、provisioner、物理存储的链路

k8s的StorageClass存储类和pv、pvc、provisioner、物理存储的链路 StorageClass能自动创建pv 在控制器中&#xff0c;直接声明storageClassName&#xff0c;不仅能自动创建pvc&#xff0c;也能自动创建pv stoageclass来自于provisioner&#xff0c;provisioner来自于pod&#x…...

【移动编程技术】作业1 中国现代信息科技发展史、Android 系统概述与程序结构 作业解析

单选题&#xff08;共 20 题&#xff0c;每题 5 分&#xff0c;满分 100 分&#xff09; (单选题) 1946 年第一台计算机问世&#xff0c;计算机的发展经历了 4 个时代&#xff0c;它们是&#xff08;&#xff09;。 选项&#xff1a; A. 模拟计算机、数字计算机、混合计算机、智…...

SQL Server数据库异常-[SqlException (0x80131904): 执行超时已过期] 操作超时问题及数据库日志已满的解决方案

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;获得2024年博客之星荣誉证书&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开发技术&#xff0c…...

使用ollama部署本地大模型(没有GPU也可以),实现IDEA和VS Code的git commit自动生成

详情 问豆包&#xff0c;提示词如下&#xff1a;收集下ollama相关信息&#xff0c;包括但不限于&#xff1a;官网地址/GitHub地址/文档地址 官网地址 https://ollama.com/ GitHub 地址 https://github.com/ollama/ollama 文档地址 https://github.com/ollama/ollama/blo…...

线程同步与互斥(上)

上一篇&#xff1a;线程概念与控制https://blog.csdn.net/Small_entreprene/article/details/146704881?sharetypeblogdetail&sharerId146704881&sharereferPC&sharesourceSmall_entreprene&sharefrommp_from_link我们学习了线程的控制及其相关概念之后&#…...

ngx_test_full_name

定义在 src\core\ngx_file.c static ngx_int_t ngx_test_full_name(ngx_str_t *name) { #if (NGX_WIN32)u_char c0, c1;c0 name->data[0];if (name->len < 2) {if (c0 /) {return 2;}return NGX_DECLINED;}c1 name->data[1];if (c1 :) {c0 | 0x20;if ((c0 &…...

R 列表:深入解析及其在数据分析中的应用

R 列表&#xff1a;深入解析及其在数据分析中的应用 引言 在R语言中&#xff0c;列表&#xff08;List&#xff09;是一种非常重要的数据结构&#xff0c;它允许将不同类型的数据项组合在一起。列表在数据分析、统计建模以及数据可视化中扮演着关键角色。本文将深入探讨R列表…...