Spring boot框架下的RocketMQ消息中间件
1. RocketMQ 基础概念
1.1 核心概念
以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式:
Producer(生产者)
定义:Producer 是负责发送消息到 RocketMQ 的组件。它可以将消息发送到指定的 Topic。
实际代码: 使用 RocketMQTemplate 提供的 API 发送消息。
@Service
public class DemoProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;public void sendMessage(String topic, String message) {rocketMQTemplate.convertAndSend(topic, message);System.out.println("Message sent to topic: " + topic);}
}
Consumer(消费者)
定义:Consumer 是负责接收和处理从 RocketMQ 中接收到的消息的组件。
实际代码: 使用 @RocketMQMessageListener 注解标注的类来实现消费者功能。
@Service
@RocketMQMessageListener(topic = "demo-topic", consumerGroup = "demo-consumer-group")
public class DemoConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received message: " + message);}
}
Topic(主题)
定义:Topic 是消息分类的基本单元,Producer 将消息发送到 Topic,Consumer 从 Topic 中接收消息。
实际代码: Topic 是通过代码中指定的字符串定义的,例如 demo-topic。
- Producer 中指定 Topic:
rocketMQTemplate.convertAndSend("demo-topic", "Hello RocketMQ!"); - Consumer 中监听 Topic:
@RocketMQMessageListener(topic = "demo-topic", consumerGroup = "demo-consumer-group")
Message(消息)
定义:消息是 Producer 发送到 Topic 的载体,包含消息体和属性。
实际代码示例:
- 发送简单文本消息:
rocketMQTemplate.convertAndSend("demo-topic", "Hello RocketMQ!"); - 发送带属性的消息:
Message message = MessageBuilder.withPayload("Hello with properties").setHeader("key", "value").build(); rocketMQTemplate.syncSend("demo-topic", message);
1.2 消息模型
点对点(Queue)模型
定义:
-
每条消息只能被一个消费者(Consumer)消费。
-
消息会被存储在一个队列(Queue)中,消费者从队列中拉取消息。
-
适合任务分发、负载均衡等场景。
特点:
-
消息独占性:一条消息只能被一个消费者消费。
-
负载均衡:如果有多个消费者属于同一个消费者组(Consumer Group),消息会均匀分配给组内的消费者。
-
消息顺序性:在 RocketMQ 中,队列(Queue)是 Topic 的底层实现,每个 Queue 内的消息是有序的。
实现:
-
在 RocketMQ 中,Queue 是 Topic 的底层实现,开发者无需直接配置 Queue,只需关注 Topic 和 Consumer Group。
-
多个消费者属于同一个 Consumer Group 时,消息会按照负载均衡策略分配给组内的消费者。
发布订阅(Topic)模型
定义:
-
消息会被广播给所有订阅了该 Topic 的消费者。
-
每个消费者都会收到相同的消息。
-
适合广播通知、事件分发等场景。
特点:
-
消息广播:一条消息会被发送给所有订阅了该 Topic 的消费者。
-
消费者独立性:每个消费者独立消费消息,彼此之间没有影响。
-
无负载均衡:所有消费者都会收到相同的消息,而不是分配不同的消息。
实现:
-
在 RocketMQ 中,可以通过设置
MessageModel.BROADCASTING来实现广播消费。 -
每个消费者都会收到 Topic 中的所有消息。
示例:在 Spring Boot 中实现广播消费
@RocketMQMessageListener(topic = "broadcast-topic",consumerGroup = "broadcast-group",messageModel = MessageModel.BROADCASTING
)
public class BroadcastConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Broadcast received: " + message);}
}
两者的核心区别
| 特性 | 点对点(Queue)模型 | 发布订阅(Topic)模型 |
|---|---|---|
| 消息消费方式 | 一条消息只能被一个消费者消费 | 一条消息会被所有消费者消费 |
| 负载均衡 | 支持,消息会均匀分配给组内的消费者 | 不支持,所有消费者收到相同消息 |
| 适用场景 | 任务分发、订单处理等需要负载均衡的场景 | 广播通知、事件分发等需要广播的场景 |
| 消费者组的作用 | 组内消费者共享消息,实现负载均衡 | 组内消费者各自独立消费所有消息 |
| 消息顺序性 | 单个 Queue 内的消息是有序的 | 无顺序性,所有消费者收到相同消息 |
2. 环境准备
2.1 安装与运行 RocketMQ
1. 下载 RocketMQ
-
访问 RocketMQ 的官方 GitHub 仓库:Apache RocketMQ GitHub
-
下载最新版本的 RocketMQ 二进制包(例如:
rocketmq-all-x.x.x-bin-release.zip)。 -
解压下载的文件
2. 启动 NameServer
-
NameServer 是 RocketMQ 的注册中心,负责管理 Broker 的路由信息。
-
启动 NameServer:
sh bin/mqnamesrv & -
检查 NameServer 是否启动成功:查看日志文件
logs/rocketmqlogs/namesrv.log,确认是否有以下内容:The Name Server boot success...
3. 启动 Broker
-
Broker 是 RocketMQ 的消息存储和转发服务器。
-
启动 Broker,并指定 NameServer 地址:
sh bin/mqbroker -n localhost:9876 autoCreateTopicEnable=true &-
-n localhost:9876:指定 NameServer 的地址。 -
autoCreateTopicEnable=true:允许自动创建 Topic。
-
-
检查 Broker 是否启动成功:
-
查看日志文件
logs/rocketmqlogs/broker.log,确认是否有以下内容:The broker boot success...
-
4. 验证 RocketMQ 运行状态
-
使用 RocketMQ 提供的工具命令检查服务状态:
sh bin/mqadmin clusterList -n localhost:9876 - 如果看到 Broker 和 NameServer 的信息,说明 RocketMQ 已成功启动。
2.2 RocketMQ Dashboard
RocketMQ Dashboard 是一个可视化管理工具,用于监控和管理 RocketMQ 的 Topic、Producer、Consumer 等信息。
1. 下载 RocketMQ Dashboard
-
访问 RocketMQ Dashboard 的官方 GitHub 仓库:RocketMQ Dashboard GitHub
-
下载最新版本的 Dashboard 二进制包(例如:
rocketmq-dashboard-x.x.x.jar)。
2. 部署 RocketMQ Dashboard
-
使用以下命令启动 Dashboard:
java -jar rocketmq-dashboard-x.x.x.jar -
默认情况下,Dashboard 会监听
8080端口。
3. 访问 RocketMQ Dashboard
-
打开浏览器,访问
http://localhost:8080。 -
在 Dashboard 页面中,配置 NameServer 地址(例如:
localhost:9876),然后点击连接。
4. 监控和管理 RocketMQ
-
Topic 管理:查看所有 Topic 的详细信息,包括消息堆积情况、生产者、消费者等。
-
Producer 管理:查看生产者的运行状态和消息发送情况。
-
Consumer 管理:查看消费者的运行状态和消息消费情况。
-
消息查询:支持按 Message ID、Topic、Key 等条件查询消息。
-
集群状态:查看 NameServer 和 Broker 的运行状态。
3. Spring Boot 集成 RocketMQ 的依赖配置
3.1 添加依赖
在 pom.xml 文件中添加 Spring Boot 提供的 RocketMQ 集成 Starter 依赖:
<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.1</version> <!-- 确保版本为你需要的最新稳定版 -->
</dependency>
3.2 配置文件
在 application.properties 或 application.yml 中配置 RocketMQ 的相关属性。
# 指定 RocketMQ NameServer 地址
rocketmq.name-server=127.0.0.1:9876# 配置生产者组名称
rocketmq.producer.group=demo_producer_group# 配置消费者组名称
rocketmq.consumer.group=demo_consumer_group
配置项说明
| 配置项 | 说明 |
|---|---|
rocketmq.name-server | RocketMQ NameServer 的地址,格式为 IP:Port,例如 127.0.0.1:9876。 支持集群地址,多个地址用分号分隔,例如:127.0.0.1:9876;127.0.0.2:9876。 |
rocketmq.producer.group | 生产者组的名称,用于标识一组生产者。 |
rocketmq.consumer.group | 消费者组的名称,用于标识一组消费者。 |
rocketmq.access-key | 如果使用阿里云 RocketMQ,需要配置 Access Key。 |
rocketmq.secret-key | 如果使用阿里云 RocketMQ,需要配置 Secret Key。 |
rocketmq.send-message-timeout | 生产者发送消息的超时时间,默认值为 3000(单位:毫秒)。 |
rocketmq.consumer.consume-thread-nums | 消费者消费消息的线程数,默认值为 |
| rocketmq.consumer.maxReconsumeTimes | 自定义重试次数,消息消费失败会自动重试,默认最大重试次数为 16 次(包括第一次消费) |
4. Spring Boot 集成 RocketMQ 的消息生产与消费
RocketMQTemplate 是否需要定义为 Bean?
-
不需要手动定义:在 Spring Boot 项目中,
RocketMQTemplate已经由rocketmq-spring-boot-starter自动配置为 Bean,因此可以直接通过@Autowired注入使用。 -
自动配置原理:
-
rocketmq-spring-boot-starter会在启动时自动创建RocketMQTemplate的实例。 -
只要在
application.properties或application.yml中正确配置了 RocketMQ 的相关参数(如rocketmq.name-server),Spring Boot 就会自动完成初始化。
-
发送非 String 类型的消息
-
支持任意类型:
RocketMQTemplate支持发送任意类型的消息,包括 POJO(普通 Java 对象)。 -
实现方式:
-
RocketMQ 会自动将消息序列化为 JSON 格式(默认使用 Jackson)。
-
消费者接收时,RocketMQ 会自动将 JSON 反序列化为对应的 Java 对象。
-
示例代码
发送 POJO 消息:
public class User {private String name;private int age;// 省略 getter 和 setter
}// 生产者
public void sendUserMessage(String topic, User user) {rocketMQTemplate.convertAndSend(topic, user);System.out.println("Sent user message: " + user);
}
消费 POJO 消息:
@Service
@RocketMQMessageListener(topic = "user_topic",consumerGroup = "user_consumer_group"
)
public class UserConsumer implements RocketMQListener<User> {@Overridepublic void onMessage(User user) {System.out.println("Received user message: " + user.getName() + ", age: " + user.getAge());}
}
4.1 消息生产(Producer)
一般会定义一个消息生产者类,然后其他类调用这个类包装好的消息发送方法。
发送普通消息
使用场景:发送简单的文本或对象消息。
实现方式:使用 RocketMQTemplate.convertAndSend(topic, message) 方法发送消息。
示例代码:
@Autowired
private RocketMQTemplate rocketMQTemplate;public void sendSimpleMessage(String topic, String message) {rocketMQTemplate.convertAndSend(topic, message);System.out.println("Sent simple message: " + message);
}
发送带 Tag 的消息
使用场景:通过 Tag 对消息进行分类,消费者可以根据 Tag 过滤消息。
实现方式:在 Topic 后添加 :Tag。消息目的地的格式为:topic:tag。
示例代码:
public void sendMessageWithTag(String topic, String tag, String message) {String destination = topic + ":" + tag; // 格式:topic:tagrocketMQTemplate.convertAndSend(destination, message);System.out.println("Sent message with tag: " + message);
}
发送同步消息
使用场景:需要确保消息成功发送到 Broker 的场景。
实现方式:使用 RocketMQTemplate.syncSend(destination, message) 方法。
示例代码:
public void sendSyncMessage(String topic, String message) {SendResult sendResult = rocketMQTemplate.syncSend(topic, message);System.out.println("Sync message sent, result: " + sendResult);
}
发送异步消息
使用场景:不需要立即确认消息是否发送成功,通过回调处理发送结果。
实现方式:使用 RocketMQTemplate.asyncSend(destination, message, sendCallback) 方法。
示例代码:
public void sendAsyncMessage(String topic, String message) {rocketMQTemplate.asyncSend(topic, message, new SendCallback() {@Overridepublic void onSuccess(SendResult sendResult) {System.out.println("Async message sent successfully: " + sendResult);}@Overridepublic void onException(Throwable throwable) {System.err.println("Async message send failed: " + throwable.getMessage());}});
}
发送单向消息
使用场景:适用于不需要确认的日志、监控等场景。
实现方式:
使用 RocketMQTemplate.sendOneWay(destination, message) 方法。
示例代码:
public void sendOneWayMessage(String topic, String message) {rocketMQTemplate.sendOneWay(topic, message);System.out.println("One-way message sent: " + message);
}
4.2 消息消费(Consumer)
基础消费逻辑
实现方式:
-
实现
RocketMQListener接口:-
消费者类必须实现
RocketMQListener<T>接口,并指定泛型类型(如String或自定义 POJO)。
-
-
重写
onMessage方法:-
在
onMessage方法中编写消息处理逻辑。
-
-
使用
@RocketMQMessageListener注解:-
通过注解指定监听的 Topic 和 Consumer Group。
-
示例代码:
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Service
@RocketMQMessageListener(topic = "demo_topic", // 监听的 TopicconsumerGroup = "demo_consumer_group" // 消费者组名称
)
public class DemoConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received message: " + message);}
}
消费消息的确认机制
自动确认:
RocketMQ 默认会自动确认消息(ACK),消费者成功消费消息后,Broker 会认为消息已处理。
手动确认:
如果需要手动确认消息,可以使用 RocketMQListener<MessageExt> 并调用 ack 方法。
消费失败的处理
重试机制:
-
如果消费者消费消息失败,RocketMQ 会尝试重新投递消息。
-
默认重试次数为 16 次,重试间隔逐渐增加。
死信队列:
-
如果消息重试多次后仍然失败,会被投递到死信队列(DLQ,Dead Letter Queue)。
-
死信队列的命名规则为:
%DLQ% + Consumer Group。
-
自动创建:
-
RocketMQ 会自动为每个 Consumer Group 创建一个死信队列,无需手动配置。
-
例如,如果 Consumer Group 为
demo_consumer_group,则死信队列的topic为%DLQ%demo_consumer_group。
-
-
手动消费死信队列:
-
可以创建一个消费者,专门消费死信队列中的消息。
-
@Service
@RocketMQMessageListener(topic = "%DLQ%demo_consumer_group", // 死信队列名称consumerGroup = "dlq_consumer_group" // 死信队列的消费者组
)
public class DLQConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received DLQ message: " + message);// 处理死信消息,例如记录日志或人工干预}
}
消费带 Tag 的消息
实现方式:
在 @RocketMQMessageListener 中指定 selectorExpression 来过滤 Tag。
示例代码:
@Service
@RocketMQMessageListener(topic = "demo_topic",consumerGroup = "demo_consumer_group",selectorExpression = "tagA || tagB" // 过滤 Tag
)
public class TagConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received tagged message: " + message);}
}
顺序消费
-
RocketMQ 默认是并发消费,不保证消息的顺序性。
-
顺序消费是指消息按照发送顺序被消费,适用于对消息顺序有严格要求的场景。
-
实现顺序消费需要:
-
生产者发送消息时指定相同的消息组。
-
消费者设置
consumeMode = ConsumeMode.ORDERLY。
-
-
顺序消费的实现依赖于队列的顺序性和消费者的单线程消费。
示例代码:
@Service
@RocketMQMessageListener(topic = "demo_topic",consumerGroup = "demo_consumer_group",consumeMode = ConsumeMode.ORDERLY // 顺序消费
)
public class OrderlyConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received orderly message: " + message);}
}
5. Spring Boot 集成 RocketMQ 的高级功能
5.1 延时消息
延时消息是指消息发送后,不会立即被消费者消费,而是在指定的延迟时间后才会被投递。RocketMQ 提供了 18 个固定的延迟级别,每个级别对应不同的延迟时间。
延迟级别与时间对应关系
| 延迟级别 | 延迟时间 |
|---|---|
| 1 | 1 秒 |
| 2 | 5 秒 |
| 3 | 10 秒 |
| 4 | 30 秒 |
| 5 | 1 分钟 |
| 6 | 2 分钟 |
| 7 | 3 分钟 |
| 8 | 4 分钟 |
| 9 | 5 分钟 |
| 10 | 6 分钟 |
| 11 | 7 分钟 |
| 12 | 8 分钟 |
| 13 | 9 分钟 |
| 14 | 10 分钟 |
| 15 | 20 分钟 |
| 16 | 30 分钟 |
| 17 | 1 小时 |
| 18 | 2 小时 |
使用场景
-
订单超时未支付取消。
-
定时任务触发。
-
延迟通知。
实现步骤
-
构建消息:使用
MessageBuilder构建消息,并设置MessageConst.PROPERTY_DELAY_TIME_LEVEL属性与等级值。 -
发送消息:使用
RocketMQTemplate.syncSend发送消息。
示例代码
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.apache.rocketmq.common.message.MessageConst;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;@Service
public class DelayedMessageProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;/*** 发送延迟消息** @param topic 主题* @param message 消息内容* @param delayLevel 延迟级别(1-18)*/public void sendDelayedMessage(String topic, String message, int delayLevel) {// 构建消息,设置延迟级别Message<String> msg = MessageBuilder.withPayload(message).setHeader(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(delayLevel)).build();// 发送延迟消息rocketMQTemplate.syncSend(topic, msg);System.out.println("Sent delayed message: " + message + ", delay level: " + delayLevel);}
}
调用消息生产者发送消息
delayedMessageProducer.sendDelayedMessage("my-topic", "Delayed Message", 3); // 延迟 10 秒
5.2 事务消息
事务消息用于实现分布式事务,确保业务操作和消息发送的一致性。RocketMQ 的事务消息分为两个阶段:
-
发送半消息:消息发送到 Broker,但暂时对消费者不可见。
-
提交或回滚:根据本地事务的执行结果,提交或回滚消息。
使用场景
-
分布式事务场景,例如订单创建和库存扣减。
-
需要保证业务操作和消息发送一致性的场景。
实现步骤
-
定义事务监听器:实现
RocketMQLocalTransactionListener接口,定义本地事务逻辑和回查逻辑。 -
使用注解@RocketMQTransactionListener:通过
txProducerGroup属性指定事务组的名称。事务组的名称必须与发送事务消息时指定的txProducerGroup一致。txProducerGroup是事务组的唯一标识,用于关联生产者和事务监听器。 -
发送事务消息:使用
rocketMQTemplate.sendMessageInTransaction方法发送事务消息。
示例代码
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;@Component
@RocketMQTransactionListener(txProducerGroup = "my-transaction-group")
public class MyTransactionListener implements RocketMQLocalTransactionListener {/*** 执行本地事务** @param msg 消息* @param arg 附加参数* @return 事务状态*/@Overridepublic RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {try {// 执行本地事务System.out.println("Executing local transaction: " + msg.getPayload());// 模拟业务操作成功return RocketMQLocalTransactionState.COMMIT;} catch (Exception e) {// 本地事务执行失败,回滚消息return RocketMQLocalTransactionState.ROLLBACK;}}/*** 回查本地事务状态** @param msg 消息* @return 事务状态*/@Overridepublic RocketMQLocalTransactionState checkLocalTransaction(Message msg) {// 回查本地事务状态System.out.println("Checking local transaction: " + msg.getPayload());return RocketMQLocalTransactionState.COMMIT;}
}
checkLocalTransaction 是 RocketMQLocalTransactionListener 接口中的一个方法,用于 回查本地事务的状态。它的作用是:
事务状态回查:
-
如果生产者发送事务消息后,未及时返回本地事务的执行结果,RocketMQ 会调用
checkLocalTransaction方法回查事务状态。
返回事务状态:根据回查结果,返回 RocketMQLocalTransactionState 枚举值:
-
COMMIT:提交事务,消息对消费者可见。 -
ROLLBACK:回滚事务,消息被丢弃。 -
UNKNOWN:事务状态未知,RocketMQ 会继续回查。
定义消息生产者发送事务消息
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;@Service
public class TransactionMessageProducer {@Autowiredprivate RocketMQTemplate rocketMQTemplate;/*** 发送事务消息** @param topic 主题* @param message 消息内容*/public void sendTransactionMessage(String topic, String message) {// 构建消息Message<String> msg = MessageBuilder.withPayload(message).build();// 发送事务消息rocketMQTemplate.sendMessageInTransaction("my-transaction-group", topic, msg, null);System.out.println("Sent transaction message: " + message);}
}
-
withPayload(message):设置消息的有效负载(Payload),即消息的内容。 -
message可以是任意类型的对象,RocketMQ 会自动将其序列化为字节数组。
调用消息生产者发送消息
transactionMessageProducer.sendTransactionMessage("my-topic", "Transaction Message");
5.3 消息过滤
RocketMQ 支持通过 Tag 或 SQL92 表达式 过滤消息,消费者可以只接收符合条件的消息。
使用 Tag 过滤
-
Tag 是消息的标签,用于对消息进行分类。
-
消费者可以订阅指定 Tag 的消息。
示例代码
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Service
@RocketMQMessageListener(topic = "my-topic",consumerGroup = "my-consumer-group",selectorExpression = "tagA || tagB" // 过滤 Tag
)
public class TagFilterConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received filtered message: " + message);}
}
生产者发送带 Tag 的消息
public void sendMessageWithTag(String topic, String tag, String message) {String destination = topic + ":" + tag; // 格式:topic:tagrocketMQTemplate.syncSend(destination, message);System.out.println("Sent message with tag: " + message);
}
使用 SQL92 表达式过滤
-
SQL92 表达式 可以根据消息的属性进行更复杂的过滤。
-
需要在 Broker 配置中启用 SQL92 过滤功能。
示例代码
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.annotation.SelectorType;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Service;@Service
@RocketMQMessageListener(topic = "my-topic",consumerGroup = "my-consumer-group",selectorType = SelectorType.SQL92, // 使用 SQL92 过滤selectorExpression = "age > 18" // 过滤条件
)
public class SqlFilterConsumer implements RocketMQListener<String> {@Overridepublic void onMessage(String message) {System.out.println("Received SQL filtered message: " + message);}
}
生产者发送消息时设置属性
public void sendMessageWithProperties(String topic, String message) {Message<String> msg = MessageBuilder.withPayload(message).setHeader("age", 20) // 设置消息属性.build();rocketMQTemplate.syncSend(topic, msg);System.out.println("Sent message with properties: " + message);
}相关文章:
Spring boot框架下的RocketMQ消息中间件
1. RocketMQ 基础概念 1.1 核心概念 以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式: Producer(生产者) 定义:Producer 是负责发送消息到 RocketMQ 的组件。它可以将消息发送到指定的 Topic。 实…...
记录一次 centos 启动失败
文章目录 现场1分析1现场2分析2搜索实际解决过程 现场1 一次断电,导致 之前能正常启动的centos 7.7 起不来了有部分log , 关键信息如下 [1.332724] XFS(sda3): Internal error xfs ... at line xxx of fs/xfs/xfs_trans.c [1.332724] XFS(sda3): Corruption of in-memory data…...
C++学习第五天
创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。 提示:以下是本篇文章正文内容,下面案例可供参考 一、构造函数 问题1 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下…...
openharmony标准系统方案之瑞芯微RK3568移植案例
标准系统方案之瑞芯微RK3568移植案例 本文章是基于瑞芯微RK3568芯片的DAYU200开发板,进行标准系统相关功能的移植,主要包括产品配置添加,内核启动、升级,音频ADM化,Camera,TP,LCD,…...
深入理解 SSH 端口转发:本地 vs 远程 vs 动态转发
🌟 简介 SSH 端口转发(SSH Port Forwarding)作为一种强大而灵活的技术,不仅可以帮助我们安全地访问远程服务,还能轻松突破网络限制。本文将带你深入了解 SSH 端口转发的原理、类型和实战应用。 🌈 目录 &a…...
postman请求参数化
postman界面介绍 一、使用环境变量(Environment Variables)进行参数化 1、在请求中使用环境变量 在请求的url、请求头(Headers)、请求体(Body)等部分都可以使用环境变量。 URL 部分示例 点击 Postman 界面右上角的 “眼睛” 图标(Environment Quick Look)打开环境管理…...
基于 WEB 开发的汽车养护系统设计与实现
标题:基于 WEB 开发的汽车养护系统设计与实现 内容:1.摘要 本文介绍了基于 WEB 开发的汽车养护系统的设计与实现。文章首先阐述了系统的背景和目的,即随着汽车保有量的增加,汽车养护需求日益增长,传统的汽车养护方式已经无法满足人们的需求&…...
Nginx正向代理配置
Nginx 正向代理默认只支持 http 协议,不支持 https 协议,需借助 "ngx_http_proxy_connect_module" 模块实现 https 正向代理,详情请参考: https://github.com/chobits/ngx_http_proxy_connect_module 安装Nginx某些模块…...
本地仓库管理之当前分支内的操作
以刚搭建好的git仓库为例,刚搭建完的仓库只有master分支,使用git branch查看当前的分支情况。 elfubuntu:~/work/example/hello$ git branch *所在分支为当前分支,即master分支 当前分支进行源码修改时简单流程图如下: 在当前分…...
《内网穿透:网络拓展与安全防护的平衡艺术》
一、引言:开启内网穿透的大门 在当今数字化浪潮席卷全球的时代,网络已成为人们生活和工作中不可或缺的一部分。我们日常使用的网络,如同一个庞大而复杂的生态系统,其中内网和外网犹如两个相互关联却又有所区别的世界。 想象一下…...
【python写个可以运行的2048小游戏】
写一个完整的2048小游戏在Python中是一个相对复杂的任务,因为它涉及到用户界面、事件处理、游戏逻辑等多个方面。为了简化这个过程,我们可以使用Python的图形库,比如pygame。下面是一个简单的2048游戏的实现。 首先,确保你已经安…...
【Flink系列】9. Flink容错机制
9. 容错机制 在Flink中,有一套完整的容错机制来保证故障后的恢复,其中最重要的就是检查点。 9.1 检查点(Checkpoint) 9.1.1 检查点的保存 1)周期性的触发保存 “随时存档”确实恢复起来方便,可是需要我…...
DETR论文阅读
1. 动机 传统的目标检测任务需要大量的人工先验知识,例如预定义的先验anchor,NMS后处理策略等。这些人工先验知识引入了很多人为因素,且较难处理。如果能够端到端到直接生成目标检测结果,将会使问题变得很优雅。 2. 主要贡献 提…...
关于vite+vue3+ts项目中env.d.ts 文件详解
env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示,特别是在使用一些特定于 Vite 的功能时(如 import.meta.env)。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...
如何优化Elasticsearch大文档查询?
记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的,各种闸口数据及产品数据都是存储在ES的(有的是独立索引,有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…...
Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正
Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正 1 添加依赖2 测试代码3 测试结果 在OpenCV中,仿射变换(Affine Transformation)和透视变换(Perspective Transformation)是两种常用的图像几何变换方法。 变换方…...
Linux中DataX使用第一期
简介 DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS, databen…...
[Qt]事件-鼠标事件、键盘事件、定时器事件、窗口改变事件、事件分发器与事件过滤器
目录 前言:Qt与操作系统的关系 一、Qt事件 1.事件介绍 2.事件的表现形式 常见的Qt事件: 常见的事件描述: 3.事件的处理方式 处理鼠标进入和离开事件案例 控件添加到对象树底层原理 二、鼠标事件 1.鼠标按下和释放事件(单击&#x…...
关于机器学习的一份总结
在之前的文章中分别有详细的关于机器学习中某一学习算法的介绍,但缺少一个总体关于机器学习的总结,所以在这篇文中就是关于机器学习的一份总结。 在最近的日子中,人工智能日益火热起来,而机器学习是其中举足轻重的一部分…...
推荐一个开源的轻量级任务调度器!TaskScheduler!
大家好,我是麦鸽。 这次推荐一款轻量级的嵌入式任务调度器,目前已经有1.4K的star,这个项目比较轻量化,只有5个源文件,可以作为学习的一个开源项目。 核心文件 项目概述: 这是一个轻量级的协作式多任务处理&…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
