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

Spring-kafka消费者消费的一些问题

前言

Spring Kafka 无缝集成了 Spring Boot、Spring Framework 及其生态系统中的其他项目,如 Spring Cloud。通过与 Spring Boot 的自动配置结合,开发者可以快速启动和配置 Kafka 相关的功能。无需编写大量样板代码即可实现 Kafka 的生产和消费功能,在公司内部微服务项目中大量使用了该框架,以下是个人的一些记录。

笔者环境:springboot-2.7.14, java version “1.8.0_401”


一、Spring-kafka是什么?

Spring Kafka 是 Spring 框架的一个项目,旨在简化与 Apache Kafka 的集成。它提供了一组用于与 Kafka 通信的高级抽象和便利功能,使开发人员可以更轻松地在 Spring 应用程序中使用 Kafka 进行消息传递。

1. 什么是 Apache Kafka?

Apache Kafka 是一个分布式流处理平台,广泛用于构建实时数据管道和流应用程序。它具有以下几个关键功能:

  • 发布和订阅记录流:类似于消息队列或企业消息传递系统。
  • 存储记录流:存储数据流容错。
  • 处理记录流:实时或批处理方式处理数据流。

2. 什么是 Spring Kafka?

Spring Kafka 是 Spring 框架的一个子项目,提供了用于与 Kafka 集成的便捷工具和抽象。Spring Kafka 包含在 Spring Boot 项目中,使得 Kafka 消息处理在 Spring 应用程序中变得更加容易和直观。

3. Spring Kafka 的主要功能

KafkaTemplate:用于发送消息的模板类。
@KafkaListener:用于消费消息的注解,支持自动并发和分区分配。
KafkaMessageListenerContainer:低级别的消息监听容器,提供了更大的灵活性。
事务支持:支持与 Kafka 的事务集成,确保消息的原子性和一致性。
错误处理:支持各种错误处理机制,包括重试、死信队列等。

4. 典型使用场景

  • 消息驱动的微服务:使用 Kafka 作为微服务之间的消息传递中介。
  • 实时数据处理:处理流式数据,如日志收集、监控和分析。
  • 事件溯源:使用Kafka 记录所有事件,支持事件溯源和审计。
  • 数据集成:连接不同的数据源和目标系统,实现数据集成和同步。

二、如何使用进行消息消费?

只需要简单四步步即可:引入依赖,配置消费者配置文件,配置 kafka configuration , 配置消费者监听器

1. 引入maven依赖

     <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency>

2. 配置文件

以下仅用于参考:

server:port: 8080
logging:level:root: info
spring:datasource:url: jdbc:mysql://localhost:3306/testusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver# 开启事务管理transaction:management:enabled: truekafka:bootstrap-servers: localhost:9092# 消费监听接口监听的主题不存在时,默认会报错listener:missing-topics-fatal: falsetemplate:default-topic: eventsproducer:# 当retris为0时,produce不会重复。retirs重发,此时repli节点完全成为leader节点,不会产生消息丢失。retries: 0#procedure要求leader在考虑完成请求之前收到的确认数,用于控制发送记录在服务端的持久化,其值可以为如下:#acks = 0 如果设置为零,则生产者将不会等待来自服务器的任何确认,该记录将立即添加到套接字缓冲区并视为已发送。在这种情况下,无法保证服务器已收到记录,并且重试配置将不会生效(因为客户端通常不会知道任何故障),为每条记录返回的偏移量始终设置为-1。#acks = 1 这意味着leader会将记录写入其本地日志,但无需等待所有副本服务器的完全确认即可做出回应,在这种情况下,如果leader在确认记录后立即失败,但在将数据复制到所有的副本服务器之前,则记录将会丢失。#acks = all 这意味着leader将等待完整的同步副本集以确认记录,这保证了只要至少一个同步副本服务器仍然存活,记录就不会丢失,这是最强有力的保证,这相当于acks = -1的设置。#可以设置的值为:all, -1, 0, 1acks: 1# 指定消息key和消息体的编解码方式key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializer# 每次批量发送消息的数量,produce积累到一定数据,一次发送#batch-size: 16384# produce积累数据一次发送,缓存大小达到buffer.memory就发送数据#buffer-memory: 33554432consumer:# 指定默认消费者group id --> 由于在kafka中,同一组中的consumer不会读取到同一个消息,依靠groud.id设置组名group-id: events-group-1# smallest和largest才有效,如果smallest重新0开始读取,如果是largest从logfile的offset读取。一般情况下我们都是设置smallestauto-offset-reset: earliest# enable.auto.commit:true --> 设置自动提交offsetenable-auto-commit: true#如果'enable.auto.commit'为true,则消费者偏移自动提交给Kafka的频率(以毫秒为单位),默认值为5000。auto-commit-interval: 100# 指定消息key和消息体的编解码方式key-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializerproperties:spring.json.value.default.type: com.tan.kafka.model.Event# 配置消费主题和消费者组2
kafka:topic: events_testgroup-2: events-group-2group-3: events-group-3group-5: events-group-5

里面的注释已经非常清晰了,相信都能看懂。

3. 配置kafka 消费者配置并使用注解启用


@EnableKafka
@Configuration
@Slf4j
public class KafkaConsumerConfig {/*** 创建一个Kafka消费者工厂,用于生产特定配置的Kafka消费者。* @param consumerFactory* @return*/@Beanpublic ConcurrentKafkaListenerContainerFactory<String, Event> kafkaListenerContainerFactory(ConsumerFactory<String, Event> consumerFactory) {ConcurrentKafkaListenerContainerFactory<String, Event> factory = new ConcurrentKafkaListenerContainerFactory<>();factory.setConsumerFactory(consumerFactory);log.info("KafkaListenerContainerFactory created.");return factory;}/*** 创建一个Kafka消费者工厂,用于生产特定配置的Kafka消费者。* 这个方法的主要作用是配置消费者的各项参数,包括连接服务器、消费者组ID、序列化器等,* 以便消费者能够正确地从Kafka主题中消费消息。** @return ConsumerFactory<String, Event> 返回一个配置好的消费者工厂,用于创建字符串键和Event值的消费者实例。*/@Beanpublic ConsumerFactory<String, Event> consumerFactory() {// 初始化配置属性映射,用于设置消费者的配置参数。Map<String, Object> configProps = new HashMap<>();// 配置Kafka服务器的连接地址和端口。configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");// 配置消费者的组ID,用于标识消费者属于哪个消费组。configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "events-group");// 配置键和值的反序列化器,这里使用StringDeserializer和JsonDeserializer。// StringDeserializer用于反序列化键,JsonDeserializer用于反序列化值,并且信任所有包,设置默认值类型为Event类。configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);configProps.put(JsonDeserializer.TRUSTED_PACKAGES, "*");configProps.put(JsonDeserializer.VALUE_DEFAULT_TYPE, Event.class);// 使用配置属性映射创建并返回一个默认的Kafka消费者工厂。return new DefaultKafkaConsumerFactory<>(configProps);}
}

⚠️ 这里的@EnableKafka 必不可少,因为它的主要作用是启用Kafka相关的注解,例如 @KafkaListener。当你在Spring Boot应用程序中使用 @EnableKafka 注解时,Spring会扫描你的项目,找到所有标注了 @KafkaListener 的方法,并创建相应的Kafka监听器容器来处理Kafka消息。

4. 配置监听器

/*** 同主题配置不同的消费组测试:每个消费者都可以获取到相同的消息* 同主题一个分区只能被多个相同消费组中的一个消费者消费*/
@Service
public class EventConsumer {@Value("${kafka.topic}")public String topic;@Value("${kafka.group-2}")public String groupId;/*** 写法 1:指定具体消费者 topic,消费者组(这里消费者组可以覆盖消费者工厂中配置的消费者组)** @param event*/@KafkaListener(topics = "events", groupId = "events-group-1")public void consume(Event event) {System.out.println("Consumed event: " + event);}/*** 写法 2:使用 SpEL(Spring Expression Language)进行动态属性解析*  Spring 使用 SpEL 来解析注解中的表达式。在 Spring Kafka 中,*  __listener 提供了一种方式来引用当前监听器 bean 的上下文,从而可以动态地访问和配置监听器的属性。* * @param message*/@KafkaListener(topics = "#{__listener.topic}", groupId = "#{__listener.groupId}")public void consume2(Event message) {System.out.println("Consumed message: " + message);}/*** 写法 3:指定不同的消费者组** @param event*/@KafkaListener(topics = "${kafka.topic}", groupId = "${kafka.group-3}")public void consume3(Event event) {System.out.println("Consumer group-3 consumed event: " + event);}/*** 写法 4:* 1. 设置 ID 方便启动、和停止消费者* 2.可以指定 autoStartup 属性为 false,手动启动消费者,默认情况下是 true* @param event*/@KafkaListener(id = "eventListener", topics = "events_test", groupId = "default", autoStartup = "true")public void consume5(Event event) {System.out.println("[event-listener] consumed event: " + event);}
}

注意:
__listener 特殊引用
__listener 是一个指向当前 Kafka 监听器的特殊 bean 引用。
通过使用 #{__listener.propertyName} 的方式,可以访问当前监听器 bean 的属性和方法。

以上不同的写法都可以,根据需要可以直接写消费者相关信息,也可以通过配置文件变量等方式获取,选择适合自己的即可。一般用配置变量的方式。

启动 springboot项目,然后发送消息,即可查看消息是否已经消费到了。

三、如何控制消费者启动和暂停?

上文中,我们可以在消费者的监听中加入autoStartup 来控制监听器是否在启动的时候开始进行消费监听,当然这种方式不够灵活,我们可以写一个接口在需要的时候进行启动和暂停,以下是个示例。

  1. 编写控制器

import com.tan.kafka.service.KafkaListenerControlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Description 控制消费者是否启动消费或者暂停* @Author zhengqiang.tan* @Date 2024/6/16 09:39*/
@RestController
@RequestMapping("/kafka")
public class KafkaController {@Autowiredprivate KafkaListenerControlService kafkaListenerControlService;@PostMapping("/pause")public String pause() {kafkaListenerControlService.pauseListener();return "Paused";}@PostMapping("/resume")public String resume() {kafkaListenerControlService.resumeListener();return "Resumed";}
}
  1. 编写服务类

/*** Kafka监听器控制服务*/
@Service
@Slf4j
public class KafkaListenerControlService {@Autowiredprivate KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry;@PostConstructpublic void checkListeners() {log.info("KafkaListenerControlService.checkListeners");for (String listenerId : kafkaListenerEndpointRegistry.getListenerContainerIds()) {MessageListenerContainer container = kafkaListenerEndpointRegistry.getListenerContainer(listenerId);if (container != null) {System.out.println("Registered Kafka listener: " + listenerId);} else {System.out.println("No Kafka listener found with id: " + listenerId);}}}/*** 暂停指定名称的Kafka监听器。* <p>* 本方法旨在提供一种方式来暂停应用程序中特定的Kafka监听器。这可能在需要临时停止处理新消息,* 例如进行系统维护或升级时的场景下非常有用。* 这里使用 eventListener 仅用于测试。** @see KafkaListenerEndpointRegistry#getListenerContainer(String) 用于获取指定名称的监听器容器* @see MessageListenerContainer#pause() 用于暂停监听器容器,使其停止接收和处理新消息*/public void pauseListener() {// 通过监听器端点注册表获取名为"eventListener"的监听器容器MessageListenerContainer container = kafkaListenerEndpointRegistry.getListenerContainer("eventListener");// 检查容器是否为空,如果非空,则调用其pause方法暂停监听器if (container != null) {container.pause();log.info("Paused Kafka listener,id = {}", container.getListenerId());}}/*** 恢复指定名称的Kafka监听器。* 此方法用于暂停后的监听器重新启动,以便它可以继续处理消息。* 它首先从注册表中获取名为"eventListener"的监听器容器,* 然后检查容器是否为空。如果容器存在,则调用其resume方法来恢复监听器的运行。* 最后,记录一条信息表明监听器已恢复。** @see KafkaListenerEndpointRegistry#getListenerContainer(String)* @see MessageListenerContainer#resume()*/public void resumeListener() {// 从注册表中获取名为"eventListener"的监听器容器MessageListenerContainer container = kafkaListenerEndpointRegistry.getListenerContainer("eventListener");// 检查容器是否存在,如果存在,则恢复容器的运行if (container != null) {container.resume();// 记录恢复操作的信息,包括监听器的IDlog.info("Resumed Kafka listener,id = {}", container.getListenerId());}}
}

通过以上方式,实测中符合预期,先暂停,然后发送消息后未进行消费,等到 resume之后继续消费。
如下所示:

curl --location --request POST 'http://localhost:8080/kafka/resume' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Host: localhost:8080' \
--header 'Connection: keep-alive' \
--data-raw ''

在这里插入图片描述

四、如何保证消费者启停过程的线程安全问题?

如果pauseListener()方法被多个线程同时访问,可能会出现竞态条件或导致未定义的行为。尽管在这个特定的代码片段中不容易直接判断线程安全性问题。因此我在这里进行了完善,确保多线程并发访问下的安全性,以上写法太过繁琐,可以参考如下代码方式。

Slf4j
@RestController
@RequestMapping("/consumer")
public class KafkaController2 {private final ReentrantLock lock = new ReentrantLock();@Autowiredprivate KafkaListenerEndpointRegistry registry;/*** 开启消费者监听,线程安全版本* @param listenerName*/@GetMapping("/start/{listenerName}")public void start(@PathVariable String listenerName) {try {lock.lock();if (!isListenerRunning(listenerName)) {log.info("start {} ... ", listenerName);startListener(listenerName);}resumeListener(listenerName);log.info("resume {} is done. ", listenerName);} finally {lock.unlock();}}/*** 暂停指定名称的监听器。这有助于提高代码的灵活性和可维护性,* 允许在不修改代码的情况下暂停不同的监听器。** @param listenerName 监听器的名称。*/@GetMapping("/pause/{listenerName}")public void pauseListener(@PathVariable String listenerName) {if (registry == null) {log.error("Registry is not available.");return;}try {MessageListenerContainer listenerContainer = registry.getListenerContainer(listenerName);if (listenerContainer == null) {log.warn("No listener container found with name: " + listenerName);return;}log.info("Attempting to pause listener: " + listenerName);listenerContainer.pause();log.info(listenerName + " pause is done.");} catch (Exception e) {log.error("Failed to pause listener " + listenerName + ": " + e.getMessage(), e);}}@Asyncprotected void startListener(String listenerName) {try {Objects.requireNonNull(registry.getListenerContainer(listenerName)).start();} catch (Exception e) {log.error("Failed to start the eventListener", e);}}@Asyncprotected void resumeListener(String listenerName) {try {Objects.requireNonNull(registry.getListenerContainer(listenerName)).resume();} catch (Exception e) {log.error("Failed to resume the eventListener", e);}}private boolean isListenerRunning(String listenerName) {try {return Objects.requireNonNull(registry.getListenerContainer(listenerName)).isRunning();} catch (Exception e) {log.error("Error checking if the eventListener is running", e);return false;}}
}

最终,我在测试完后结果是符合预期的,先暂停,然后持续发送消息,观察有无收到消息,然后在重新启动监听即可。

curl --location --request GET 'http://localhost:8080/consumer/pause/eventListener' 	

在这里插入图片描述

其他

批量消息发送脚本,以下是个参考

#!/bin/bash
cd /Users/mac/apps/kafka
# 主题名称
TOPIC="events_test"# Kafka 主机和端口
BROKER="localhost:9092"# 生产随机消息的数量(只需修改这里进行控制发送消息数量)
NUM_MESSAGES=1# 生成一个 5 位随机数
generate_random_number() {RANDOM_NUMBER=$(shuf -i 10000-99999 -n 1)echo $RANDOM_NUMBER
}# 生成随机消息并发送到 Kafka 主题
for i in $(seq 1 $NUM_MESSAGES); doID=$(date +%s) # 生成Long类型的唯一IDMSG_ID=$(uuidgen)MESSAGE="Random message $(generate_random_number)"JSON_MESSAGE="{\"id\":\"$ID\", \"msgId\":\"$MSG_ID\", \"message\":\"$MESSAGE\"}"echo $JSON_MESSAGE | bin/kafka-console-producer.sh --broker-list $BROKER --topic $TOPIC
doneecho "Produced $NUM_MESSAGES JSON messages to the topic '$TOPIC'."

总结

以上内容介绍了使用 spring和 kafka集成进行消费的使用过程,对消费者的配置和以及对消费者的启动和暂停实践,详细介绍了配置各个步骤。不足之处,未提及异常处理,批量消费,消费者动态扩缩提升消费能力的问题,这些后面在陆续补充。

如果觉得有用,不妨点赞,关注一波,下期再会~😄

相关文章:

Spring-kafka消费者消费的一些问题

前言 Spring Kafka 无缝集成了 Spring Boot、Spring Framework 及其生态系统中的其他项目&#xff0c;如 Spring Cloud。通过与 Spring Boot 的自动配置结合&#xff0c;开发者可以快速启动和配置 Kafka 相关的功能。无需编写大量样板代码即可实现 Kafka 的生产和消费功能&…...

【自我提升】提升能量书籍

《原子习惯》 (Atomic Habits) - 詹姆斯克利尔 (James Clear)&#xff1a; 核心思想&#xff1a;微小的习惯改变可以带来显著的生活变化。方法&#xff1a; 将大目标拆分为可管理的小习惯。使用“习惯堆叠”技术&#xff0c;将新习惯与已有习惯结合。创建支持性环境&#xff0c…...

python图像处理库-PIL(Pillow)

PIL库全称为Python Imaging Library&#xff0c;即Python图像处理库&#xff0c;是一个在Python中用于处理图像的非常流行的库。 一、PIL介绍 这个库提供了广泛的文件格式支持、高效的内部表示以及相当强大的图像处理功能。 核心图像库旨在快速访问存储在几种基本像素格式中的数…...

【2024】kafka streams的详细使用与案例练习(2)

目录 前言使用1、整体结构1.1、序列化 2、 Kafka Streams 常用的 API2.1、 StreamsBuilder2.2、 KStream 和 KTable2.3、 filter和 filterNot2.4、 map 和 mapValues2.5、 flatMap 和 flatMapValues2.6、 groupByKey 和 groupBy2.7、 count、reduce 和 aggregate2.8、 join 和 …...

qt 简单实验 读取json格式的配置文件

1.概要 2.代码 //#include "mainwindow.h"#include <QApplication> #include <QFile> #include <QJsonDocument> #include <QJsonObject> #include <QDebug> //读取json数据的配置文件QJsonObject readJsonConfigFile(const QString …...

Docker常用命令与实战示例

docker 1. 安装2. 常用命令3. 存储4. 网络5. redis主从复制示例6. wordpress示例7. DockerFile8. 一键安装超多中间件&#xff08;compose&#xff09; 1. 安装 以centOS系统为例 # 移除旧版本docker sudo yum remove docker \docker-client \docker-client-latest \docker-c…...

数据结构(基础知识)

基础概念&#xff1a; 数据&#xff1a;数据是信息的载体&#xff0c;是描述客观事物属性的数&#xff0c;字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合 数据元素&#xff1a;是数据的基本单位&#xff0c;在程序中常作为一个整体来考虑 数据对象&#…...

计算机网络:网络层 - 路由选择协议

计算机网络&#xff1a;网络层 - 路由选择协议 路由器的结构路由选择协议概述自治系统 AS内部网关协议路由信息协议 RIP距离向量算法RIP报文格式收敛问题 开放最短路径优先 OSPF基本工作原理自治系统分区 外部网关协议BGP-4 路由器的结构 如图所示&#xff0c;路由器被分为路由…...

JupyterLab使用指南(六):JupyterLab的 Widget 控件

1. 什么是 Widget 控件 JupyterLab 中的 Widget 控件是一种交互式的小部件&#xff0c;可以用于创建动态的、响应用户输入的界面。通过使用 ipywidgets 库&#xff0c;用户可以在 Jupyter notebook 中创建滑块、按钮、文本框、选择器等控件&#xff0c;从而实现数据的交互式展…...

OpenCV 特征点检测与匹配

一 OpenCV特征场景 ①图像搜索&#xff0c;如以图搜图&#xff1b; ②拼图游戏&#xff1b; ③图像拼接&#xff0c;将两长有关联得图拼接到一起&#xff1b; 1 拼图方法 寻找特征 特征是唯一的 可追踪的 能比较的 二 角点 在特征中最重要的是角点 灰度剃度的最大值对应的…...

css布局之flex应用

/*父 100*/.parent-div {/* 这里添加你想要的属性 */display: flex;flex-direction: row; //行justify-content: space-between; //左右对齐align-items: center;flex-wrap: wrap; //换行}/*中 90 10 */.middle-div {/* 这里添加你想要的属性 */display: flex;flex-direction:…...

树莓派4B设置AP热点步骤

树莓派4B设置AP热点步骤&#xff1a;先进入root模式 预先进行apt-get update 第1步&#xff1a;安装network-manager ​sudo apt-get install network-manager第2步&#xff1a;安装git apt-get install git apt-get install util-linux procps hostapd iproute2 iw haveged …...

Java程序之百鸡百钱问题

题目&#xff1a; 百钱买百鸡的问题算是一套非常经典的不定方程的问题&#xff0c;题目很简单&#xff1a;公鸡5文钱一只&#xff0c;母鸡3文钱一只&#xff0c;小鸡3只一文钱&#xff0c;用100文钱买一百只鸡,其中公鸡&#xff0c;母鸡&#xff0c;小鸡都必须要有&#xff0c;…...

Mybatis——动态sql

if标签 用于判断条件是否成立。使用test属性进行条件判断&#xff0c;如果条件为true&#xff0c;则拼接sql。 <where>标签用于识别语句是否需要连接词and&#xff0c;识别sql语句。 package com.t0.maybatisc.mapper;import com.t0.maybatisc.pojo.Emp; import org.a…...

可视化大屏开发系列——页面布局

页面布局是可视化大屏的基础&#xff0c;想要拥有一个基本美观的大屏&#xff0c;就得考虑页面整体模块的宽高自适应&#xff0c;我们自然就会想到具有强大灵活性flex布局&#xff0c;再借助百分比布局来辅助。至此&#xff0c;大屏页面布局问题即可得到解决。 可视化大屏开发系…...

Python statistics 模块

Python 的 statistics 模块提供了一组用于执行各种统计计算的函数&#xff0c;包括平均值、中位数、标准差、方差以及其他统计量。让我来简单介绍一下。 首先&#xff0c;你可以使用以下方式导入 statistics 模块&#xff1a; python import statistics 接下来&#xff0c;…...

wireshark常见使用表达式

目录 1. 捕获过滤器 (Capture Filters)基本捕获过滤器组合捕获过滤器 2. 显示过滤器 (Display Filters)基本显示过滤器复杂显示过滤器协议特定显示过滤器 3. 进阶显示过滤器技巧使用函数和操作符逻辑操作符 4. 常见网络协议过滤表达式示例HTTP 协议HTTPS 协议DNS 协议DHCP 协议…...

用Java获取键盘输入数的个十百位数

这段Java代码是一个简单的程序&#xff0c;用于接收用户输入的一个三位数&#xff0c;并将其分解为个位、十位和百位数字&#xff0c;然后分别打印出来。下面是代码的详细解释&#xff1a; 导入所需类库: import java.util.Scanner;&#xff1a;导入Scanner类&#xff0c;用于从…...

第10章 启动过程组 (制定项目章程)

第10章 启动过程组 9.1制定项目章程&#xff0c;在第三版教材第356~360页&#xff1b; 文字图片音频方式 视频12 第一个知识点&#xff1a;主要输出 1、项目章程&#xff08;重要知识点&#xff09; 项目目的 为了稳定与发展公司的客户群(抽象&#xff0c;非具体) 可测量的项目…...

html侧导航栏客服栏

ico 替换 ICO <html xmlns"http://www.w3.org/1999/xhtml"><head><meta http-equiv"Content-Type" content"text/html; charsetutf-8"><title>返回顶部</title><script src"js/jquery-2.0.3.min.js"…...

Clonable接口和拷贝

Hello~小伙伴们&#xff01;本篇学习Clonable接口与深拷贝&#xff0c;一起往下看吧~(画图水平有限&#xff0c;两张图&#xff0c;&#xff0c;我真的画了巨久&#xff0c;求路过的朋友来个3连~阿阿阿~~~) 目录 1、Clonable接口概念 2、拷贝 2、1浅拷贝 2、2深拷贝 1、Clon…...

关于小蛋の编程和小蛋编程为同一作者的说明

小蛋の编程和小蛋编程的作品为同一人制作&#xff0c;因前者为父母的手机号进行注册&#xff0c;现用本人手机号注册了新账号小蛋编程&#xff0c;后续文章将在新账号小蛋编程上进行刊登&#xff0c;同时在小蛋编程上对原账号文章进行转载。此账号不再发布帖子&#xff0c;请大…...

大数据平台之Spark

Apache Spark 是一个开源的分布式计算系统&#xff0c;主要用于大规模数据处理和分析。它由UC Berkeley AMPLab开发&#xff0c;并由Apache Software Foundation维护。Spark旨在提供比Hadoop MapReduce更快的处理速度和更丰富的功能&#xff0c;特别是在处理迭代算法和交互式数…...

How to use ModelSim

How to use ModelSim These are all written by a robot Remember, you can only simulate tb files....

【专业英语 复习】第8章 Communications and Networks

1. 单选题 One of the most dramatic changes in connectivity and communications in the past few years has been ____. A. widespread use of mobile devices with wireless Internet connectivity B. chat rooms C. satellite uplinks D. running programs on rem…...

运行vue3项目相关报错

1. VSCode打开TSVue3项目很多地方报错 报错内容 几乎所有文件都会出现未知飘红 error Delete CR prettier/prettier报错原因 插件冲突&#xff0c;Windows系统回车换行符与MAC不一致&#xff08;所以这个问题Windows系统才会出现&#xff09; 解决 需要安装Vue - Official…...

2024年6月计算机视觉论文推荐:扩散模型、视觉语言模型、视频生成等

6月还有一周就要结束了&#xff0c;我们今天来总结2024年6月上半月发表的最重要的论文&#xff0c;重点介绍了计算机视觉领域的最新研究和进展。 Diffusion Models 1、Autoregressive Model Beats Diffusion: Llama for Scalable Image Generation LlamaGen&#xff0c;是一个…...

Centos Stream9 和Centos Stream10的下载网址

Index of /https://mirror.stream.centos.org/...

chrome 录制器及性能分析工具的使用

需求背景&#xff1a; 对比不同VPN方案网络延迟的差异。 验证工具&#xff1a; chrome浏览器自带的录制器、性能插件可以完美的解决这个问题。 注意&#xff1a;录制的操作都在当前页面&#xff0c;不存在新开标签页的场景 解决方案&#xff1a; 使用chrome录制器&#xf…...

如何打造稳定、好用的 Android LayoutInspector?

速度极慢&#xff0c;遇到复杂的布局经常超时 某些情况无法选中指定的 View 本文将围绕 LayoutInspector 的痛点&#xff0c;分析问题并修复&#xff0c;最终将 LayoutInspector 变成一个稳定、好用的插件。 二、加速 Dump View Hierarchy 2.1 问题描述 开发复杂业务的同学…...

C++ Thead互斥量死锁,mutex如何防止死锁---C++11多线程快速学习

假设有两个线程 T1 和 T2&#xff0c;它们需要对两个互斥量 mtx1 和 mtx2 进行访问&#xff0c;而且需要按照以下顺序获取互斥量的所有权&#xff1a; - T1 先获取 mtx1 的所有权&#xff0c;再获取 mtx2 的所有权。 - T2 先获取 mtx2 的所有权&#xff0c;再获取 mtx1 的所有…...

Ubuntu 之Glade图形化设计器

演示环境说明&#xff1a;本机使用Windows 11 家庭版本搭载 Ubuntu 22.04.4 LTS 子系统&#xff0c;同时并安装Ubuntu桌面虚拟化软件XLaunch。 如果没有搭建好上述问题&#xff0c;请参考&#xff1a;windows11子系统Ubuntu 22.04.4子安装图形化界面 Glade是什么&#xff1f;…...

152. 乘积最大子数组

152. 乘积最大子数组 题目链接&#xff1a;152. 乘积最大子数组 代码如下&#xff1a; class Solution { public:int maxProduct(vector<int>& nums) {int resnums[0];vector<int> f(nums.size()1,0),g(nums.size()1,0);f[0]nums[0],g[0]nums[0];for(int i1…...

proactor模式

Proactor模式是一种异步I/O的设计模式&#xff0c;它允许程序直接发起一个异步I/O操作并立即返回&#xff0c;而不需要等待该操作完成。一旦I/O操作实际完成&#xff0c;系统会通知相应的完成处理程序&#xff08;Completion Handler&#xff09;&#xff0c;该处理程序随后执行…...

Charles抓包工具

一、charles简介 1&#xff0c;charles是什么 Charles中文名叫青花瓷&#xff0c;它是一款基于HTTP协议的代理服务器&#xff0c;通过成为电脑或者浏览器的代理&#xff0c;然后截取请求和请求结果达到分析抓包的目的。 特点:跨平台、半免费 2&#xff0c;charles工作原理 前…...

RabbitMQ如何保证消息可靠

解决办法&#xff1a; 1、做好消息确认机制&#xff08;pulisher、consumer[手动ACK]&#xff09; 2、每一个发送的消息都在数据库做好记录。定期将失败的消息再次发送一遍 消息确认机制&#xff1a; 生产者确认模式&#xff1a;确认消息是否发送到broker&#xff0c;失败…...

学习笔记——路由网络基础——路由的高级特性

七、路由的高级特性 1、路由迭代(路由递归) 路由必须有直连的下一跳才能够指导转发&#xff0c;静态路由或BGP路由的下一跳可能不是直连的邻居&#xff0c;因此需要计算出一个直连的下一跳和对应的出接口&#xff0c;这个过程就叫做路由迭代(路由递归)。 添加一条去往20.1.1.…...

网络编程之XDP、TC和IO_URING以及DPDK

一、网络编程常见的技术 在前面已经分析过了XDP、TC和eBPF。也基本把三者间的关系理清了&#xff0c;但现在又有一个疑惑涌了上来。在前面提到过的IO_URING和DPDK与这些技术有什么关系呢&#xff1f;其实只要认真的看过分析文章可能大家心里都已经基本清楚了。 正如在前面不断…...

晶谷高温烧结导电浆料用低熔点玻璃粉 晶谷耐高温导电漆导电油墨高温玻璃粉

晶谷浆料玻璃粉是一种用于电子浆料的材料&#xff0c;它在电子浆料中起到粘结和降低烧结温度的作用&#xff0c;能够提高浆料与基材之间的结合力。 浆料玻璃粉的性能特点包括&#xff1a; - 软化点&#xff1a;软化点在350至650度之间。 - 热膨胀系数&#xff1a;热膨胀系数…...

【Mysql】DQL操作单表、创建数据库、排序、聚合函数、分组、limit关键字

DQL操作单表 1.1 创建数据库 •创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8;•将db1数据库中的 emp表 复制到当前 db2数据库 ** 1.2 排序** 通过 ORDER BY 子句,可以将查询出的结果进行排序 (排序只是显示效果,不会影响真实数据) 语法结构&#xff1a;…...

Excel 常用技巧(四)

Microsoft Excel 是微软为 Windows、macOS、Android 和 iOS 开发的电子表格软件&#xff0c;可以用来制作电子表格、完成许多复杂的数据运算&#xff0c;进行数据的分析和预测&#xff0c;并且具有强大的制作图表的功能。由于 Excel 具有十分友好的人机界面和强大的计算功能&am…...

【Linux 基础】文件与目录管理

1. 文件和目录的基本概念 文件&#xff1a;是数据的集合&#xff0c;可以是文本、图像、视频等。 目录&#xff08;也称为文件夹&#xff09;&#xff1a;是文件和子目录的集合&#xff0c;用于组织文件。 2. 目录和路径 绝对路径&#xff1a;从根目录&#xff08;/&#x…...

C++系列-String(一)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” string是用于字符串&#xff0c;可以增删改查 首先&#xff0c;我们来看一下string的底层 接下来&#xff0c;我们来看一下string的常用接口有哪些&#xff1a; #define _CRT_S…...

服务器硬件的基础知识

引言 服务器是现代数据中心和企业IT基础设施的核心组成部分。了解服务器硬件的基本知识不仅有助于选择和维护服务器&#xff0c;还能提高系统性能和可靠性。本文将详细介绍服务器硬件的各个方面&#xff0c;包括处理器、内存、存储、网络、散热和电源等&#xff0c;帮助读者全…...

java基于ssm+jsp 汽车在线销售系统

1 前台功能模块 网站首页 网页首页汽车在线销售系统模块如下&#xff1a;首页、汽车信息、新闻资讯、留言反馈、我的收藏管理等功能图1 图1网页首页 网页前台车辆信息效果图如图2所示 图2 车辆信息界面图 2 管理员功能模块 管理员输入个人的账号、密码登录系统&#xff0c…...

【干货】Android中高级开发进阶必备资料(附:PDF+视频+源码笔记)

4、数据传输与序列化 5、Java虚拟机原理 6、高效IO 设计思想解读开源框架 随着互联网企业的不断发展&#xff0c;产品项目中的模块越来越多&#xff0c;用户体验要求也越来越高&#xff0c;想实现小步快跑、快速迭代的目的越来越难&#xff0c;插件化技术应用而生。如果没有…...

AI通用写作模版,可以在此基础上进行修改

指令 角色 作者 &#xff1a;你是一位自媒体爆文写作专家&#xff0c;负责撰写文章&#xff0c;具备对特定主题的深入理解和一定的写作技巧。读者 &#xff1a;25-55岁通用人群&#xff0c;对资讯新闻类感兴趣&#xff0c;需要易于理解且富有启发性的内容。 技能 研究能力&…...

openEuler2203SP3自定义ios

需求&#xff1a; 1、legacy启动 2、/boot分区1G&#xff0c;剩余给/&#xff0c;lvm分区 3、创建root密码和一个普通用户user&#xff0c;密码Hello2024 4、服务器安装&#xff08;选上development、legacy-unix、security-tools&#xff09; 5、关闭firewalld、selinux …...

一年又一年志愿

--第一篇 20220624十年苦读&#xff0c;青春飞扬&#xff0c;其道大光&#xff0c;来日方长。又是一年高考时&#xff0c;高考改变命运&#xff0c;但是后面还有更关键几步&#xff0c;跟大家一起聊聊。之前写我考状元的经历&#xff0c;堂弟考省前十的经历&#xff0c;有不少…...

NL2SQL进阶系列(1):DB-GPT-Hub、SQLcoder、Text2SQL开源应用实践详解

1. MindSQL(库) MindSQL 是一个 Python RAG&#xff08;检索增强生成&#xff09;库&#xff0c;旨在仅使用几行代码来简化用户与其数据库之间的交互。 MindSQL 与 PostgreSQL、MySQL、SQLite 等知名数据库无缝集成&#xff0c;还通过扩展核心类&#xff0c;将其功能扩展到 Sn…...