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

学习 RocketMQ 单机部署、消息发送、消息接收

文章目录

    • RocketMQ 介绍
    • 为什么要使用 MQ ?
    • RocketMQ 与其他产品对比
      • vs Kafka
      • vs RabbitMQ
      • vs ActiveMQ
    • RocketMQ 重要概念
    • 部署 Namesrver、Broker、Dashboard
    • 快速入门
      • 消息生产者
      • 消息消费者
    • 消费模式
    • 简单消息
      • 1)同步发送
      • 2)异步发送
      • 3)单向发送
    • 顺序消息
      • 顺序消息生产者
      • 顺序消息消费者
    • 广播消息
      • 广播消息消费模式
    • 延迟消息
      • 预定日程生产者
      • 预定日程消费者
      • 指定时间生产者
      • 指定时间消费者
    • RocketMQ 如何保证消息可靠性?
    • RocketMQ 如何解决消息积压问题?

RocketMQ 介绍

RocketMQ是一款由阿里巴巴开源的分布式消息中间件。它具有低延迟、高吞吐量、高可用性和高可靠性等特点,适用于构建具有海量消息堆积和异步解耦功能的应用系统。

为什么要使用 MQ ?

作用描述
异步系统耦合度降低,没有强依赖关系
削峰不需要同步执行的远程调用可以有效提高响应时间
解耦请求达到峰值后,后端或者数据库还可以保持固定消费速率消费,不会被压垮

RocketMQ 与其他产品对比

vs Kafka

  • 数据可靠性:RocketMQ 提供多种可靠性保证,Kafka 在极端情况下可能丢失数据。
  • 实时性:RocketMQ 在消息实时性上表现更佳。
  • 队列数与性能:RocketMQ 支持更多队列,Kafka 在高分区下性能下降。
  • 消息顺序性:RocketMQ 支持严格顺序,Kafka 可能产生乱序。
  • 生态:Kafka 生态更丰富,RocketMQ 与阿里技术栈集成好。

vs RabbitMQ

  • 性能:RocketMQ 在高并发和海量消息处理上表现更优。
  • 消息模型:RabbitMQ 模型灵活,RocketMQ 注重顺序和事务。
  • 适用场景:RabbitMQ 适用于可靠消息传递,RocketMQ 适用于高性能场景。

vs ActiveMQ

  • 跨平台与持久化:ActiveMQ 支持多种协议和数据库持久化,RocketMQ 持久化机制高效。
  • 灵活性:ActiveMQ 协议广泛,RocketMQ 多语言SDK集成友好。
  • 社区与文档:ActiveMQ 社区活跃度较低,RocketMQ 开发活跃但社区成熟度不及 RabbitMQ。

总结:RocketMQ 在数据可靠性、实时性、队列数与性能上具有优势,适合高性能和顺序消息场景。

RocketMQ 重要概念

Producer:消息的发送者,生产者 (发件人)

Consumer:消息接收者,消费者 (取件人)

Broker:暂时和传输消息的通道 (快递)

NameServer:管理Broker的;负责消息的存储和转发,接收生产者产生的消息并持久化消息;当用户发送的消息被发送到Broker时,Broker会将消息转发到与之关联的Topic中,以便让更多的接收者进行处理;各个快递公司的管理机构,相当于Broker的注册中心,保留了broker的信息 (监测快递是否健康)

Queue:队列,消息存放的位置,一个Broker中可以有多个队列 (驿站)

Topic:主题,消息的分类,用于标识同一类业务逻辑的消息 (取件码)

ConsumerGroup:消费者组,RocketMQ 中承载多个消费行为一致的消费者负载均衡分组。和消费者不同,消费者组是一个逻辑概念。

部署 Namesrver、Broker、Dashboard

Docker部署RocketMQ5.x (单机部署+配置参数详解+不使用docker-compose直接部署)_rocketmq不推荐用docker部署-CSDN博客

快速入门

1)创建一个基于 Maven 的 SpringBoot 项目,并添加以下依赖

<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5.1.0</version>
</dependency>

消息生产者

  1. 创建消息生产者producer,并指定生产者组名
  2. 指定Nameserver地址
  3. 启动producer
  4. 创建消息对象,指定主题Topic、Tag和消息体
  5. 发送消息
  6. 关闭生产者
public class SyncProducer {public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {DefaultMQProducer producer = new DefaultMQProducer("SyncProducer");producer.setNamesrvAddr("10.226.8.14:9876");producer.start();for (int i = 0; i < 2; i++) {Message msg = new Message("Simple", //主题"TagA",  //设置消息Tag,用于消费端根据指定Tag过滤消息。"Simple-Sync".getBytes(StandardCharsets.UTF_8) //消息体。);SendResult send = producer.send(msg);System.out.printf(i + ".发送消息成功:%s%n", send);}producer.shutdown();}
}

消息消费者

  1. 创建消费者comsumer、指定消费者组名
  2. 指定Nameserver地址
  3. 创建监听订阅主题Topic和Tag等
  4. 处理消息
  5. 启动消费者comsumer
public class Consumer {public static void main(String[] args) throws Exception {DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer("SimplePushConsumer");pushConsumer.setNamesrvAddr("10.226.8.14:9876");pushConsumer.subscribe("Simple","*");pushConsumer.setMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {list.forEach( n->{System.out.printf("收到消息: %s%n" , n);});return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});pushConsumer.start();System.out.printf("Consumer Started.%n");}
}

消费模式

MQ 的消费模式可以大致分为两种,一种是推 Push,一种是拉 Pull。

Push 是服务端主动推送消息给客户端,优点是及时性较好,但如果客户端没有做好流控,旦服务端推送大量消息到客户端时,就会导致客户端消息堆积甚至崩溃。

Pull 是客户端需要主动到服务端取数据,优点是客户端可以依据自己的消费能力进行消费但拉取的频率也需要用户自己控制,拉取频繁容易造成服务端和客户端的压力,拉取间隔长又容易造成消费不及时。

Push 模式也是基于 pull 模式的,只能客户端内部封装了 api,一般场景下,上游消息生产量小或者均速的时候,选择 push 模式。在特殊场景下,例如电商大促,抢优惠券等场景可以选择 pull 模式

简单消息

1)同步发送

可靠性要求高、数据量级少、实时响应,具体实现参考上面的入门代码

2)异步发送

不等待消息返回直接进入后续流程。

public class AsyncProducer {public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {DefaultMQProducer producer = new DefaultMQProducer("AsyncProducer");producer.setNamesrvAddr("10.226.8.14:9876");producer.start();CountDownLatch countDownLatch = new CountDownLatch(100);//计数for (int i = 0; i < 100; i++) {Message message = new Message("Simple", "TagA", "Simple-Async".getBytes(StandardCharsets.UTF_8));final int index = i;producer.send(message, new SendCallback() {@Overridepublic void onSuccess(SendResult sendResult) {countDownLatch.countDown();System.out.printf("%d 消息发送成功%s%n", index, sendResult);}@Overridepublic void onException(Throwable throwable) {countDownLatch.countDown();System.out.printf("%d 消息失败%s%n", index, throwable);throwable.printStackTrace();}});}countDownLatch.await(5, TimeUnit.SECONDS);producer.shutdown();}
}

3)单向发送

只负责发送,不管消息是否发送成功。

public class OnewayProducer {public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException {DefaultMQProducer producer = new DefaultMQProducer("AsyncProducer");producer.setNamesrvAddr("10.226.8.14:9876");producer.start();for (int i = 0; i < 10; i++) {Message message = new Message("Simple","TagA", "Simple-Oneway".getBytes(StandardCharsets.UTF_8));producer.sendOneway(message);System.out.printf("%d 消息发送完成 %n" , i);}Thread.sleep(5000);producer.shutdown();}
}

顺序消息

顺序消息指生产者局部有序发送到一个queue,但多个queue之间是全局无序的。

  • 顺序消息生产者样例:通过MessageQueueSelector将消息有序发送到同一个queue中。
  • 顺序消息消费者样例:通过MessageListenerOrderly消费者每次读取消息都只从一个queue中获取(通过加锁的方式实现)。

顺序消息生产者

public class OrderProducer {public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {DefaultMQProducer producer = new DefaultMQProducer("OrderProducer");producer.setNamesrvAddr("10.226.8.14:9876");producer.start();for (int j = 0; j < 5; j++) {for (int i = 0; i < 10; i++) {Message message = new Message("OrderTopic","TagA",("order_" + j + "_step_" + i).getBytes(StandardCharsets.UTF_8));SendResult sendResult = producer.send(message, new MessageQueueSelector() {@Overridepublic MessageQueue select(List<MessageQueue> list, Message message, Object o) {Integer id = (Integer) o;int index = id % list.size();return list.get(index);}}, j);System.out.printf("%s%n", sendResult);}}producer.shutdown();}
}

顺序消息消费者

public class OrderConsumer {public static void main(String[] args) throws MQClientException {DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("OrderConsumer");consumer.setNamesrvAddr("10.226.8.14:9876");consumer.subscribe("OrderTopic","*");consumer.registerMessageListener(new MessageListenerOrderly() {@Overridepublic ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {list.forEach(n->{System.out.println("QueueId:"+n.getQueueId() + "收到消息内容 "+new String(n.getBody()));});return ConsumeOrderlyStatus.SUCCESS;}});consumer.start();System.out.printf("Consumer Started.%n");}
}

广播消息

广播消息并没有特定的消息消费者样例,这是因为这涉及到消费者的集群消费模式。

  • MessageModel.BROADCASTING:广播消息。一条消息会发给所有订阅了对应主题的消费者,不管消费者是不是同一个消费者组。
  • MessageModel.CLUSTERING:集群消息。每一条消息只会被同一个消费者组中的一个实例消费。

广播消息消费模式

public class BroadcastConsumer {public static void main(String[] args) throws Exception {DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("BroadCastConsumer");consumer.setNamesrvAddr("10.226.8.14:9876");consumer.subscribe("simple","*");consumer.setMessageModel(MessageModel.BROADCASTING); //广播模式consumer.registerMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {list.forEach(n->{System.out.println("QueueId:"+n.getQueueId() + "收到消息内容 "+new String(n.getBody()));});return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});consumer.start();System.out.printf("Broadcast Consumer Started.%n");}
}

延迟消息

延迟消息实现的效果就是在调用producer.send方法后,消息并不会立即发送出去,而是会等一段时间再发送出去。这是RocketMQ特有的一个功能。

  • message.setDelayTimeLevel(3):预定日常定时发送。1到18分别对应messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h;可以在dashboard中broker配置查看。
  • msg.setDelayTimeMs(10L):指定时间定时发送。默认支持最大延迟时间为3天,可以根据broker配置:timerMaxDelaySec修改。

预定日程生产者

public class ScheduleProducer {public static void main(String[] args) throws Exception {DefaultMQProducer producer = new DefaultMQProducer("ScheduleProducer");producer.setNamesrvAddr("10.226.8.14:9876");producer.start();for (int i = 0; i < 2; i++) {Message msg = new Message("Schedule", //主题"TagA",  //设置消息Tag,用于消费端根据指定Tag过滤消息。"ScheduleProducer".getBytes(StandardCharsets.UTF_8) //消息体。);//1到18分别对应messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2hmsg.setDelayTimeLevel(3);producer.send(msg);System.out.printf(i + ".发送消息成功:%s%n", LocalTime.now());}producer.shutdown();}
}

预定日程消费者

public class ScheduleConsumer {public static void main(String[] args) throws Exception {DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer("SimplePushConsumer");pushConsumer.setNamesrvAddr("10.226.8.14:9876");pushConsumer.subscribe("Schedule","*");pushConsumer.setMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {list.forEach( n->{System.out.printf("接收时间:%s %n", LocalTime.now());});return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});pushConsumer.start();System.out.printf("Simple Consumer Started.%n");}
}

指定时间生产者

public class TimeProducer {public static void main(String[] args) throws MQClientException, MQBrokerException, RemotingException, InterruptedException {DefaultMQProducer producer = new DefaultMQProducer("TimeProducer");producer.setNamesrvAddr("192.168.43.137:9876");producer.start();for (int i = 0; i < 2; i++) {Message msg = new Message("Schedule", //主题"TagA",  //设置消息Tag,用于消费端根据指定Tag过滤消息。"TimeProducer".getBytes(StandardCharsets.UTF_8) //消息体。);// 相对时间:延时消息。此消息将在 10 秒后传递给消费者。msg.setDelayTimeMs(10000L);// 绝对时间:定时消息。设置一个具体的时间,然后在这个时间之后多久在进行发送消息// msg.setDeliverTimeMs(System.currentTimeMillis() + 10000L);producer.send(msg);System.out.printf(i + ".发送消息成功:%s%n", LocalTime.now());}producer.shutdown();}
}

指定时间消费者

public class TimeConsumer {public static void main(String[] args) throws MQClientException {DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer("TimeConsumer");pushConsumer.setNamesrvAddr("10.226.8.14:9876");pushConsumer.subscribe("Schedule","*");pushConsumer.setMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {list.forEach( n->{System.out.printf("接收时间:%s %n", LocalTime.now());});return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});pushConsumer.start();System.out.printf("Simple Consumer Started.%n");}
}

RocketMQ 如何保证消息可靠性?

我们将消息流程分为三大部分,每一部分都有可能会丢失数据。

  • 生产阶段:Producer 通过网络将消息发送给 Broker,这个发送可能会发生丢失。比如网络延迟不可达等。
  • 存储阶段:Broker 肯定是先把消息放到内存的,然后根据刷盘策略持久化到硬盘中。刚收到 Producer 的消息,放入内存,但是异常宕机了,导致消息丢失。
  • 消费阶段:消费失败。比如先提交ack再消费,处理过程中出现异常,该消息就出现了丢失。

解决方案:

  • 生产阶段:使用同步发送失败重试机制;异步发送重写回调方法检查发送结果;ACK 确认机制。
  • 存储阶段:同步刷盘机制(默认情况下是异步刷盘);集群模式采用同步复制
  • 消费阶段:正常消费处理完成才提交ACK(手动ACK);如果处理异常返回重试标识。

RocketMQ 如何解决消息积压问题?

  1. 增加消费者数量:
    增加消费者实例的数量,以提高消息的消费速度。
    确保消费者实例数量与消息队列数量匹配,以便每个队列都有专门的消费者处理。

  2. 优化消费者逻辑:
    优化消费者的处理逻辑,提高单个消费者的处理效率。
    使用批量消费的方式来减少每次消费的开销。

  3. 扩展消息队列容量:
    增加消息队列的数量,以分散消息负载。
    动态调整队列数量,增加处理能力,实现更高的并行处理。

  4. 设置消息消费失败处理机制:
    实施重试机制,确保消费失败的消息能够被重新处理。
    设置死信队列(DLQ)来处理多次消费失败的消息。

  5. 快速失败丢弃消息:
    如果某些消息可以丢弃,考虑在高峰期快速丢弃这些消息以减轻负担。

  6. 提升系统性能:
    优化服务器性能,增加硬件资源,如CPU、内存和网络带宽。
    确保网络连接的稳定性和速度,以减少延迟。

相关文章:

学习 RocketMQ 单机部署、消息发送、消息接收

文章目录 RocketMQ 介绍为什么要使用 MQ &#xff1f;RocketMQ 与其他产品对比vs Kafkavs RabbitMQvs ActiveMQ RocketMQ 重要概念部署 Namesrver、Broker、Dashboard快速入门消息生产者消息消费者 消费模式简单消息1&#xff09;同步发送2&#xff09;异步发送3&#xff09;单…...

【计算机网络】CDN

CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;是一种分布式的服务器网络&#xff0c;旨在通过将内容缓存到多个地理位置的服务器上&#xff0c;加速内容的分发和传递。CDN 的主要目的是减少用户访问网站时的延迟&#xff0c;提升用户体验&…...

数据结构:插入排序

1.插入排序 此排序如打扑克牌一样&#xff1b;每次抓牌&#xff0c;把扑克从前向后扒拉&#xff1b;找到合适的位置插入进去—所以叫插入排序&#xff1b; 时间复杂度&#xff1a;O&#xff08;N^2&#xff09; int arr[10] { 9,8,7,6,5,4,3,2,1,0 };//数据太多就不好写了 …...

Nginx反向代理配置与负载均衡配置

简介&#xff1a;整理自黑马程序员苍穹外卖的第11节 nginx是什么&#xff1f; nginx的好处 nginx反向代理配置方式 nginx负载均衡的配置方式 nginx负责均衡策略...

axios 前端与 Django 后端的 POST 交互

背景 自己在写一些油猴脚本&#xff0c;前端需要用 JS&#xff0c;后端是自己的服务&#xff0c;是用 Python 的 Django 框架完成的。 油猴脚本中需要通过 POST 方法&#xff0c;向后端传一些数据&#xff0c;所以前端我用的是 axios 库&#xff0c;后端需要用 Django 处理 P…...

数据结构常用术语

一. 常见术语 数据相关 英文术语中文术语Data数据Data element数据元素Data item数据项Data structure数据结构Logical structure逻辑结构Data type数据类型 指针与存储 英文术语中文术语Pointer指针Sequential storage structure顺序存储结构Linked storage structure链状…...

Flask 轻松上手:从零开始搭建属于你的Web应用

引言 随着互联网技术的发展&#xff0c;Web应用程序的需求日益增长。对于开发者来说&#xff0c;选择一个合适的框架至关重要。Flask以其简洁的设计、高度的可定制性和对各种扩展的良好支持&#xff0c;成为了很多项目的基础。无论你是初学者还是有经验的开发者&#xff0c;掌…...

[MyBatis-Plus]快速入门

介绍 MyBatis-Plus是MyBatis的好朋友, 与MyBatis配合, 实现开发效率的提高 官网: 特点: 润物细无声: 只做增强不做改变, 引入它不会对现有工程产生影响, 如丝般顺滑效率自上: 只需简单配置, 即可快速进行单表CRUD, 从而节省大量时间功能丰富: 代码生产, 自动分页, 逻辑删除, …...

单例模式和读者写者问题

文章目录 10. 线程安全的单例模式10.1 什么是设计模式10.2 什么是单例模式10.3 单例模式的特点10.4 饿汉方式和懒汉方式10.5 单例模式的线程池 11. STL和智能指针的线程安全 问题11.1 STL中的容器是否是线程安全的?11.2 智能指针是否是线程安全的? 12. 其他常见的各种锁13. 读…...

内网wordpress更换IP后无法访问的解决办法

一、现象 一台装有wordpress的台式机&#xff0c;从一个校区移到了另一个校区&#xff0c;更换了IP地址&#xff0c;导致无法正常访问。 二、分析 安装wordpress的时候里面的ip&#xff08;或域名&#xff09;都已固定。安装好后&#xff0c;内网通过IP访问&am…...

Spring Boot课程答疑:技术难题一网打尽

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…...

云卷云舒【超级数据库】:算力网络时代的云原生数据库

一直关注算力网络&#xff0c;再次分析下移动云的数据库团队&#xff0c;他们在做的一些事情其实比较务实&#xff0c;在推进数据库依托云原生演进到算力网络阶段&#xff0c;这都是在构建一个能够承载无限容量、无感接入、多模融合、智能调度的超级数据库。 未来数据库&#…...

电脑分盘分盘

方案一&#xff1a;使用磁盘管理工具扩展卷功能将未分配磁盘合并到C盘 按WinR输入diskmgmt.msc并按Enter键打开磁盘管理工具。在主界面中右键单击C盘驱动器并选择“扩展卷”&#xff0c;然后按照提示流程操作即可扩展C盘空间。 WinR diskmgmt.msc 注意&#xff1a;虽然系统内置…...

四元数基础知识

背景 四元数是方向的 4 元组表示形式&#xff0c;它比旋转矩阵更简洁。 四元数对于分析涉及三维旋转的情况非常有效。 四元数广泛用于机器人技术、量子力学、计算机视觉和 3D 动画。 您可以在 Wikipedia 上了解有关基本数学概念的更多信息。 您还可以观看由 3blue1brown 制…...

『网络游戏』进入游戏主城UI跳转主城【26】

首先在Unity客户端中创建一个空节点重命名为MainCityWnd 设置父物体为全局 创建空节点钉在左上角作为角色信息UI 在钉子下创建Image 创建脚本&#xff1a;MainCityWnd.cs 编写脚本&#xff1a;MainCityWnd.cs 挂载脚本 创建脚本&#xff1a;MainCitySys.cs 编写脚本&#xff1a…...

多点低压差分(M-LVDS)线路驱动器和接收器——MS2111

MS2111 是多点低压差分 (M-LVDS) 线路驱动器和接收器。经过 优化&#xff0c;可运行在高达 200Mbps 的信号速率下。所有部件均符合 M LVDS 标准 TIA / EIA-899 。该驱动器的输出支持负载低至 30Ω 的多 点总线。 MS2111 的接收器属于 Type-2 &#xff0c; 可在 -1…...

regexp_split_to_table的作用

regexp_split_to_table 是 PostgreSQL 中的一个函数&#xff0c;用于将一个字符串根据正则表达式进行分割&#xff0c;并将结果返回为一个表格&#xff08;每个分割后的部分作为一行&#xff09;。这个函数非常有用&#xff0c;特别是在处理复杂字符串时。 语法 regexp_split…...

【MATLAB】基于RSSI的蓝牙定位程序,4个锚点、二维平面

目录 ​编辑 商品描述 主要功能 技术细节 适用场景 下载链接 商品描述 这款基于接收信号强度指示&#xff08;RSSI&#xff09;原理的蓝牙定位程序&#xff0c;专为需要高效、可靠定位解决方案的开发者和研究人员设计。它能够在二维平面内&#xff0c;通过4个锚点实现对未…...

利用 langchain 和 LLM 来给 PDF 做总结

在网上看到一个PDF, 讲的是 Gstreamer 的的动态管道的构建, 一瞥而过, 没时间细看, 先写个小程序通过 langchain 和 LLM 给它做个快速总结 代码如下 from langchain.document_loaders import UnstructuredPDFLoader from langchain.llms import OpenAI from langchain.chains i…...

props 不能轻易解构,注意maxLength类似这种,不能解构出来

当您从 props 对象中解构 msg 时&#xff0c;msg 变量将会获取到当时的 props.msg 值。解构操作仅仅是将当前值复制到 msg 变量中&#xff0c;它并不会建立响应式连接。因此&#xff0c;当 props.msg 发生变化时&#xff0c;解构出的 msg 变量仍保持其原始值&#xff0c;不会自…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...