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

「Kafka」生产者篇

「Kafka」生产者篇

生产者发送消息流程

在消息发送的过程中,涉及到了 两个线程 ——main 线程Sender 线程

在 main 线程中创建了 一个 双端队列 RecordAccumulator

main线程将消息发送给RecordAccumulator,Sender线程不断从 RecordAccumulator 中拉取消息发送到 Kafka Broker。

image-20231222155757635

  • main线程创建 Producer 对象,调用 send 函数发送消息,经过:
    • 拦截器 Interceptors(可选项,扩展一些额外功能)
    • 序列化器 Serializer(为什么不用Java的序列化?因为大数据传输需要更轻量的序列化方式)
    • 分区器 Partitioner,需要判断发送到哪个分区
  • 一个分区就会创建一个双端队列 RecordAccumulator,创建队列都是在内存里完成的,总大小默认为 32m
    • 双端队列 RecordAccumulator 还有一个内存池的概念,每次 send 数据到队列后,在存放数据的时候会从内存池中取出内存,数据发送到kafka后释放内存归还到内存池;一端创建内存,另一端释放内存,这也是它为什么设计为双端队列。
  • Sender线程从队列中拉取数据
    • 每次批处理batch.size的大小默认为 16k,延迟时间 linger.ms 默认为 0ms,没有延迟。
      • 这两个条件是 或 的关系,两个条件达到任意一个就可以发送数据。
    • 以节点的方式, key:value => Broker1:(队列数据...) 的格式发送给对应的 kafka 服务器,如果kafka没有应答,默认每个broker节点队列最多缓存 5 个请求,后续 生产经验—数据乱序 的章节会讲这个作用。
  • Selector负责打通底层的链路,IO输入流 => IO输出流,经过Selector发送到kafka集群,kafka集群进行副本的同步。
  • 如果kafka集群收到数据后,会返回 ack,有3种模式,如上图。
    • 如果ack返回成功,则先清理掉缓存的Request请求,然后清理到对应队列中的数据。
    • 如果ack返回失败,则进行 retries 重试,默认重试次数是int的最大值(死磕),一直发Request请求,直到重试成功。
    • 详细讲解请参考下文的 生产经验—数据可靠性。

生产者重要参数列表

image-20231222171445101

image-20231222171536700

image-20231222171611680

异步发送

  • 同步发送:外部数据发送到 RecordAccumulator 队列中,等待这批数据都发送到 kafka 集群,再返回。
  • 异步发送:外部数据发送到 RecordAccumulator 队列中,不管这些数据有没有发送到 kafka 集群,直接返回。
    • 默认为异步发送

普通异步发送

编写不带回调函数的代码

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;public class CustomProducer {public static void main(String[] args) throws InterruptedException {// 1. 创建 kafka 生产者的配置对象Properties properties = new Properties();// 2. 给 kafka 配置对象添加配置信息:bootstrap.serversproperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092");// key,value 序列化(必须):key.serializer,value.serializerproperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");// 3. 创建 kafka 生产者对象KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);// 4. 调用 send 方法,发送消息for (int i = 0; i < 5; i++) {// 这里只指定了topic和valuekafkaProducer.send(new ProducerRecord<>("first", "atguigu " + i));}// 5. 关闭资源kafkaProducer.close();}
}

回调异步发送

回调函数会在 producer 收到 ack 时调用,为异步调用,该方法有两个参数,分别是元数据信息(RecordMetadata)和异常信息(Exception)。

如果 Exception 为 null,说明消息发送成功,如果 Exception 不为 null,说明消息发送失败。

注意:消息发送失败会自动重试,不需要我们在回调函数中手动重试。

image-20231222165627441

// 4. 调用 send 方法,发送消息
for (int i = 0; i < 5; i++) {// 添加回调 CallbackkafkaProducer.send(new ProducerRecord<>("first", "atguigu " + i), new Callback() {// 该方法在 Producer 收到 ack 时调用,为异步调用@Overridepublic void onCompletion(RecordMetadata metadata, Exception exception) {if (exception == null) {// 没有异常,输出信息到控制台System.out.println("主题:" + metadata.topic() + "->" +"分区:" + metadata.partition());} else {// 出现异常打印exception.printStackTrace();}}});// 延迟一会会看到数据发往不同分区Thread.sleep(2);
}

同步发送

只需在异步发送的基础上,再调用一下 get() 方法即可。

image-20231222172334948

生产者分区

分区好处

image-20231222172447587

可以通过机器的存储能力自定义分区数据,比如 broker0 存储 20T 数据,broker1和2分别存储 40T 数据。

生产者发送消息的分区策略

可阅读:详解Kafka分区机制原理|Kafka 系列 二

默认的分区器 DefaultPartitioner

/*** The default partitioning strategy: 默认分区策略* 如果你指定了分区,则直接用这个分区* 如果没指定分区,但有key,则按照key的hash值 % 分区数* 如果既没指定分区也没指定key,则按照粘性分区处理。* See KIP-480 for details about sticky partitioning.*/
public class DefaultPartitioner implements Partitioner {...
}

ProducerRecord 类的构造方法就表示了这 3 种分区策略:

image-20231222173831306

自定义分区器

  • 定义类实现 Partitioner 接口

  • 重写 partition() 方法

    import org.apache.kafka.clients.producer.Partitioner;
    import org.apache.kafka.common.Cluster;
    import java.util.Map;/*** 1. 实现接口 Partitioner* 2. 实现3个方法: partition、close、configure* 3. 编写 partition 方法,返回分区号*/
    public class MyPartitioner implements Partitioner {/*** 返回信息对应的分区* @param topic 主题* @param key 消息的 key* @param keyBytes 消息的 key 序列化后的字节数组* @param value 消息的 value* @param valueBytes 消息的 value 序列化后的字节数组* @param cluster 集群元数据可以查看分区信息* @return*/@Overridepublic int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {// 获取消息String msgValue = value.toString();// 创建 partitionint partition;// 判断消息是否包含 atguiguif (msgValue.contains("atguigu")) {partition = 0;} else {partition = 1;}// 返回分区号return partition;}// 关闭资源@Overridepublic void close() {}// 配置方法@Overridepublic void configure(Map<String, ?> configs) {}
    }
    
  • 使用分区器的方法,在生产者的配置中添加分区器参数

    import org.apache.kafka.clients.producer.*;
    import org.apache.kafka.common.serialization.StringSerializer;
    import java.util.Properties;public class CustomProducerCallbackPartitions {public static void main(String[] args) {Properties properties = new Properties();properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092");properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());// 添加自定义分区器properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, "com.atguigu.kafka.producer.MyPartitioner");KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);for (int i = 0; i < 5; i++) {kafkaProducer.send(new ProducerRecord<>("first", "atguigu " + i), new Callback() {@Overridepublic void onCompletion(RecordMetadata metadata, Exception e) {if (e == null) {System.out.println("主题:" + metadata.topic() + "->" +"分区:" + metadata.partition());} else {e.printStackTrace();}}});}kafkaProducer.close();}
    }
    

生产者如何提高吞吐量

  1. 合理调整 batch.sizelinger.ms 的参数值
  2. 采用数据压缩
  3. 调整缓冲区大小

image-20231222181126685

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;public class CustomProducerParameters {public static void main(String[] args) {// 1. 创建 kafka 生产者的配置对象Properties properties = new Properties();// 2. 给 kafka 配置对象添加配置信息:bootstrap.serversproperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092");// key,value 序列化(必须):key.serializer,value.serializerproperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());// batch.size:批次大小,默认 16Kproperties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);// linger.ms:等待时间,默认 0msproperties.put(ProducerConfig.LINGER_MS_CONFIG, 1);// RecordAccumulator:缓冲区大小,默认 32M:buffer.memoryproperties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);// compression.type:压缩,默认 none,可配置值 gzip、snappy、lz4 和 zstdproperties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "snappy");// 3. 创建 kafka 生产者对象KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);// 4. 调用 send 方法,发送消息for (int i = 0; i < 5; i++) {kafkaProducer.send(new ProducerRecord<>("first", "atguigu " + i));}// 5. 关闭资源kafkaProducer.close();}
}

生产经验—数据可靠性

回顾发送流程

image-20231227174242122

数据可靠性主要根据 kafka 集群返回给我们的 ack

ack 应答原理

  • ack=0,不需要等待数据落盘应答,一直发送给 kafka,很容易丢数据。
    • 数据发送到 Leader 后,Leader 挂掉了,此时数据还在内存中,未落盘,数据丢失。
  • ack=1,不需要等待 kafka 主从同步完成,Leader 收到数据落盘后应答。
    • Leader 成功落盘,但还未同步给 Follower,Leader 挂了,数据丢失。
  • ack=-1,需要等待 Leader 和 ISR 队列里面的所有节点收齐数据后应答。

image-20231227174844019

数据完全可靠条件

image-20231227174931962

数据完全可靠条件 = ACK 级别设置为-1 + 分区副本大于等于2 + ISR里应答的最小副本数量大于等于2

注意,这里的“副本”并不是指的 Follower;在 Kafka 中,副本分为 Leader 副本和 Follower 副本。Leader 副本负责处理消息,而 Follower 副本则简单地复制 Leader 副本的数据。

也就是一个分区至少要有 1 个 Leader 和 1 个 Follower,ISR 队列最少也要有 1 个 Leader 和 1 个 Follower。

一个分区至少有 1 个 Leader,所以每个 Partition 都会有一个 ISR,而且是由 Leader 动态维护。

可靠性总结

  • acks=0,生产者发送过来数据就不管了,可靠性差,效率高;
  • acks=1,生产者发送过来数据 Leader 应答,可靠性中等,效率中等;
  • acks=-1,生产者发送过来数据 Leader 和 ISR 队列里面所有 Follwer 应答,可靠性高,效率低;
  • 在生产环境中,
    • acks=0,很少使用;
    • acks=1,一般用于传输普通日志,允许丢个别数据;
    • acks=-1,一般用于传输和钱相关的数据,对可靠性要求比较高的场景。

代码实现

// 设置 acks=-1
properties.put(ProducerConfig.ACKS_CONFIG, "all");
// 重试次数 retries,默认是 int 最大值,2147483647
properties.put(ProducerConfig.RETRIES_CONFIG, 3);

拓展:

image-20231227175355966

生产者将数据发送给 Leader,并且完成同步给 Follower,此时回复 ack 时,Leader 挂了,kafka 会挑一个 Follower 成为新的 Leader,因为生产者没有收到 ack,此时就会认为他的数据没有发送到 kafka,就会进行重试,导致新 Leader 重复接收了两份数据。

生产经验—数据去重

数据传递语义

image-20231227183602062

幂等性

幂等性原理

image-20231227183642104

如何使用幂等性

开启参数 enable.idempotence,默认为 true(默认开启)。

生产者事务

幂等性只能保证单分区单会话的不重复,一旦 kafka 挂掉重启,还是有可能产生重复数据。如果想完全去重,就必须使用事务。

Kafka 事务原理

image-20231227183743850

  • 幂等性:如果 kafka 挂掉重启,会重新生成一个 PID,所以可能会有重复。
  • 事务:kafka 根据全局唯一的 transactional.id 会划分到50个分区中的某一个分区,这些分区的信息是存储在一个特殊 Topic 里的,而 Topic 的底层就是硬盘,所以即使客户端挂掉了,重启后也能继续处理未完成的事务,因为有 transactional.id 存在。

Kafka 的事务一共有如下 5 个 API:

// 1. 初始化事务
void initTransactions();// 2. 开启事务
void beginTransaction() throws ProducerFencedException;// 3. 在事务内提交已经消费的偏移量(主要用于消费者)
void sendOffsetsToTransaction(Map<TopicPartition, OffsetAndMetadata> offsets, String consumerGroupId) throws ProducerFencedException;// 4. 提交事务
void commitTransaction() throws ProducerFencedException;// 5. 放弃事务(类似于回滚事务的操作)
void abortTransaction() throws ProducerFencedException;

单个 Producer,使用事务保证消息的仅一次发送:

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;public class CustomProducerTransactions {public static void main(String[] args) {// 1. 创建 kafka 生产者的配置对象Properties properties = new Properties();// 2. 给 kafka 配置对象添加配置信息properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092");// key,value 序列化properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());// 设置事务 id(必须),事务 id 任意起名,要求全局唯一properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, "transaction_id_0");// 3. 创建 kafka 生产者对象KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);// 初始化事务kafkaProducer.initTransactions();// 开启事务kafkaProducer.beginTransaction();try {// 4. 调用 send 方法,发送消息for (int i = 0; i < 5; i++) {// 发送消息kafkaProducer.send(new  ProducerRecord<>("first", "atguigu " + i));}// int i = 1 / 0;// 提交事务kafkaProducer.commitTransaction();} catch (Exception e) {// 终止事务kafkaProducer.abortTransaction();} finally {// 5. 关闭资源kafkaProducer.close();}}
}

生产经验—数据有序

image-20231228175454367

仅能保证单分区内有序,如果想保证全局有序,只能把所有分区的消息都拉到消费者端,进行一个全排序,再进行消费。

但需要等所有数据到齐了再进行排序,效率可能还不如单分区。

生产经验—数据乱序

一个 broker 可以有一个 broker 缓存队列,队列中存放的是还未收到 ack 的请求,最多能存放 5 个。

比如发送 Request1 后,对方没有应答,此时还可以发送 Request2、Request3、Request4、Request5,最多能发送 5 次请求。

假设在一个分区中,生产者发送了 Request1、Request2 请求都成功了,但 Request3 请求发送失败了,进行重试,但此时 Request4 请求发送成功了,然后 Request3 请求才发送成功,此时到达 kafka 的顺序就为 1 2 4 3,是乱序的。

  • kafka在1.x版本之前保证数据单分区有序,条件如下:
    • max.in.flight.requests.per.connection=1(不需要考虑是否开启幂等性)。
      • 也就是 broker 的缓存队列只允许有 1 个请求,这个请求收到 ack 后才能发送下一个。
  • kafka在1.x及以后版本保证数据单分区有序,条件如下:
    • 开启幂等性
      • max.in.flight.requests.per.connection 需要设置小于等于 5
    • 未开启幂等性
      • max.in.flight.requests.per.connection 需要设置为 1(和kafka在1.x版本之前一样)。

原因说明:因为在 kafka1.x 以后,启用幂等后,kafka 服务端最多会缓存 producer 发来的最近 5request 的元数据。

故无论如何,都可以保证最近 5request 的数据都是有序的。

image-20231228180538249

  1. 比如先来的 Request1、Request2,服务端根据 SeqNumber 判断数据是否是单调递增的,如果符合则直接进行落盘;
  2. 但下一个请求是 Request4,正常应该是 Request3,所以 Request4 这个请求只能在内存中放着,不能进行落盘;
  3. 再下一个是 Request5,同样不能进行落盘;
  4. 直到 Request3 来了,然后对他们进行排序,然后再依次落盘 Request3、Request4、Request5。

笔记整理自b站尚硅谷视频教程:【尚硅谷】Kafka3.x教程(从入门到调优,深入全面)

相关文章:

「Kafka」生产者篇

「Kafka」生产者篇 生产者发送消息流程 在消息发送的过程中&#xff0c;涉及到了 两个线程 ——main 线程和Sender 线程。 在 main 线程中创建了 一个 双端队列 RecordAccumulator。 main线程将消息发送给RecordAccumulator&#xff0c;Sender线程不断从 RecordAccumulator…...

C语言实现RSA算法加解密

使用c语言实现了RSA加解密算法&#xff0c;可以加解密文件和字符串。 rsa算法原理 选择两个大素数p和q&#xff1b;计算n p * q;计算φ(n)(p-1)(q-1)&#xff1b;选择与φ(n)互素的整数d&#xff1b;由de1 mod φ(n)计算得到e&#xff1b;公钥是(e, n), 私钥是(d, n);假设明…...

如何设计前后端分离的系统架构?

如何将前端页面和后端Java代码进行集成&#xff1f; 将前端页面和后端Java代码进行集成通常需要使用一些特定的工具和技术。以下是一些常见的方法&#xff1a; 使用RESTful API&#xff1a;REST&#xff08;Representational State Transfer&#xff09;是一种基于HTTP协议构…...

【强化学习】SARAS代码实现

前言 SARAS&#xff0c;假设环境状态和动作状态都是离散的。利用动作价值矩阵来进行行为的预测。其主要就是利用时序差分的思想&#xff0c;对动作价值矩阵进行更新。 代码实现 import gymnasium as gym import numpy as npclass sarsa():def __init__(self, states_n, acti…...

P1019 [NOIP2000 提高组] 单词接龙 刷题笔记

P1019 [NOIP2000 提高组] 单词接龙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路来自 大佬 Chardo 的个人中心 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 匹配 &#xff1a; 将 第一个字符串末尾 和第二个字符串第一个开始匹配 如果 j<i这段走完了 flag还没…...

如何实现WinApp的UI自动化测试?

WinApp&#xff08;WindowsAPP&#xff09;是运行在Windows操作系统上的应用程序&#xff0c;通常会提供一个可视的界面&#xff0c;用于和用户交互。例如运行在Windows系统上的Microsoft Office、PyCharm、Visual Studio Code、Chrome&#xff0c;都属于WinApp。常见的WinApp&…...

chrome扩展程序开发之在目标页面运行自己的JS

原文地址&#xff1a;https://qdgithub.com/home/index/article/aid/247.html chrome 插件开发的入门介绍&#xff0c;实现利用 chrome 扩展实现在目标网页运行我们的 js 的功能。关于 chrome 扩展的详细内容&#xff0c;可以通过官网了解。 开发工具很简单&#xff0c;记事本…...

NLP项目之语种识别

目录 1. 代码及解读2. 知识点n-grams仅保留最常见的1000个n-grams。意思是n1000 ? 1. 代码及解读 in_f open(data.csv) lines in_f.readlines() in_f.close() dataset [(line.strip()[:-3], line.strip()[-2:]) for line in lines] print(dataset[:5])[(1 december wereld…...

Linux lpr命令教程:如何使用lpr命令打印文件(附案例详解和注意事项)

Linux lpr命令介绍 lpr命令在Unix-like操作系统中用于提交打印任务。如果在命令行中指定了文件名&#xff0c;那么这些文件将被发送到指定的打印机&#xff08;如果没有指定目的地&#xff0c;则发送到默认目的地&#xff09;。如果命令行中没有列出文件&#xff0c;lpr将从标…...

浅谈C语言inline关键字

对于C开发者来说&#xff0c;inline是个再熟悉不过的关键字&#xff0c;因为默认的成员函数都是inline&#xff0c;也是常规高校教材中宣扬C的“优势”之一。 但是C语言其实也是支持inline关键字的&#xff0c;而且是很早期的gcc就支持了该关键字。在Linux0.12版本内核代码中也…...

Flink1.17实战教程(第六篇:容错机制)

系列文章目录 Flink1.17实战教程&#xff08;第一篇&#xff1a;概念、部署、架构&#xff09; Flink1.17实战教程&#xff08;第二篇&#xff1a;DataStream API&#xff09; Flink1.17实战教程&#xff08;第三篇&#xff1a;时间和窗口&#xff09; Flink1.17实战教程&…...

OpenCV实战 -- 维生素药片的检测记数

文章目录 检测记数原图经过操作开始进行消除粘连性--形态学变换总结实现方法1. 读取图片&#xff1a;2. 形态学处理&#xff1a;3. 二值化&#xff1a;4. 提取轮廓&#xff1a;5. 轮廓筛选和计数&#xff1a; 分水岭算法&#xff1a;逐行解释在基于距离变换的分水岭算法中&…...

【AI】注意力机制与深度学习模型

目录 一、注意力机制 二、了解发展历程 2.1 早期萌芽&#xff1a; 2.2 真正意义的注意力机制&#xff1a; 2.3 2015 年及以后&#xff1a; 2.4 自注意力与 Transformer&#xff1a; 2.5 BERT 与预训练模型&#xff1a; 三、基本框架 1. 打分函数&#xff08;Score Fun…...

HTML5和JS实现新年礼花效果

HTML5和JS实现新年礼花效果 2023兔年再见&#xff0c;2024龙年来临了&#xff01; 祝愿读者朋友们在2024年里&#xff0c;身体健康&#xff0c;心灵愉悦&#xff0c;梦想成真。 下面是用HTML5和JS实现新年礼花效果&#xff1a; 源码如下&#xff1a; <!DOCTYPE html>…...

【owt-server】一些构建项目梳理

【owt-server】清理日志&#xff1a;owt、srs、ffmpeg 【owt】p2p client mfc 工程梳理【m98】webrtc vs2017构建带符号的debug库【OWT】梳理构建的webrtc和owt mfc工程 m79的mfc客户端及owt-client...

Linux shell编程学习笔记38:history命令

目录 0 前言 1 history命令的功能、格式和退出状态1.1 history命令的功能1.2 history命令的格式1.3退出状态2 命令应用实例2.1 history&#xff1a;显示命令历史列表2.2 history -a&#xff1a;将当前会话的命令行历史追加到历史文件~/.bash_history中2.3 history -c&#xf…...

elasticsearch安装教程(超详细)

1.1 创建网络&#xff08;单点部署&#xff09; 因为我们还需要部署 kibana 容器&#xff0c;因此需要让 es 和 kibana 容器互联&#xff0c;所有先创建一个网络&#xff1a; docker network create es-net 1.2.加载镜像 采用的版本为 7.12.1 的 elasticsearch&#xff1b;…...

arkts中@Watch监听的使用

概述 Watch用于监听状态变量的变化&#xff0c;当状态变量变化时&#xff0c;Watch的回调方法将被调用。Watch在ArkUI框架内部判断数值有无更新使用的是严格相等&#xff08;&#xff09;&#xff0c;遵循严格相等规范。当在严格相等为false的情况下&#xff0c;就会触发Watch的…...

【Jmeter】Jmeter基础9-BeanShell介绍

3、BeanShell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法。 3.1、Jmeter中使用的BeanShell 在Jmeter中&#xff0c;除了配置元件&#xff0c;其他类型的元件中都有BeanShell。BeanShell 是一种完全符合Java语法规范的脚本语言,并且又拥…...

详解数组的轮转

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…...

html 表格 笔记

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>第二个页面</title><meta name"language" content"cn"> </head> <body><h2 sytle"width:500px;…...

计算机网络【HTTP 面试题】

HTTP的请求报文结构和响应报文结构 HTTP请求报文主要由请求行、请求头、空行、请求正文&#xff08;Get请求没有请求正文&#xff09;4部分组成。 1、请求行 由三部分组成&#xff0c;分别为&#xff1a;请求方法、URL以及协议版本&#xff0c;之间由空格分隔&#xff1b;请…...

linux基于用户身份对资源访问进行控制的解析及过程

linux中用户分为三类 1.超级用户&#xff08;root&#xff09; 拥有至高无上的权限 2.普通用户 人为创建、权限小&#xff0c;权限受到控制 3.程序用户 运行程序的用户&#xff0c;不是给人使用的&#xff0c;给程序使用的&#xff0c;一般不给登录&#xff01; 组账…...

手动创建idea SpringBoot 项目

步骤一&#xff1a; 步骤二&#xff1a; 选择Spring initializer -> Project SDK 选择自己的JDK版本 ->Next 步骤三&#xff1a; Maven POM ->Next 步骤四&#xff1a; 根据JDK版本选择Spring Boot版本 11版本及以上JDK建议选用3.2版本&#xff0c;JDK为11版本…...

【Go语言入门:Go语言的数据结构】

文章目录 3.Go语言的数据结构&#xff1a;3.1. 指针3.2. struct&#xff08;结构体&#xff09;3.3. Map(映射,哈希&#xff09; 3.Go语言的数据结构&#xff1a; 简介&#xff1a; 在Go语言中&#xff0c;数据结构体可以分为四种类型&#xff1a;基础类型、聚合类型、引用类型…...

QT designer的ui文件转py文件之后,实现pycharm中运行以方便修改逻辑,即添加实时模板框架

为PyCharm中的实时模板&#xff0c;你需要遵循以下步骤&#xff1a; 打开PyCharm的设置: 选择 File > Settings&#xff08;在macOS上是 PyCharm > Preferences&#xff09;。 导航到实时模板: 在设置中找到 Editor > Live Templates。 添加新的模板组 (可选): 为了…...

什么是负载均衡?

负载均衡是指在计算机网络领域中&#xff0c;将客户端请求分配到多台服务器上以实现带宽资源共享、优化资源利用率和提高系统性能的技术。负载均衡可以帮助小云有效解决单个服务器容量不足或性能瓶颈的问题&#xff0c;小云通过平衡流量负载&#xff0c;使得多台服务器能够共同…...

Python和Java的优缺点

Python的优点&#xff1a; 简单易学&#xff1a;Python的语法简洁清晰&#xff0c;易于学习和理解。丰富的库和框架&#xff1a;Python拥有庞大的标准库和活跃的开源社区&#xff0c;可以快速使用各种功能强大的库和框架&#xff0c;比如NumPy、Pandas、Django等。可读性强&am…...

AES - 在tiny-AES-c基础上封装了2个应用函数(加密/解密)

文章目录 AES - 在tiny-AES-c基础上封装了2个应用函数(加密/解密)概述增加2个封装函数的AES库aes.haes.c在官方测试程序上改的测试程序(用来测试这2个封装函数)END AES - 在tiny-AES-c基础上封装了2个应用函数(加密/解密) 概述 在github山有个星数很高的AES的C库 tiny-AES-c …...

51和32单片机读取FSR薄膜压力传感器压力变化

文章目录 简介线性电压转换模块51单片机读取DO接线方式51代码实验效果 32单片机读取AO接线方式32代码实验效果 总结 简介 FSR薄膜压力传感器是可以将压力变化转换为电阻变化的一种传感器&#xff0c;单片机可以读取然后作为粗略测量压力&#xff08;仅提供压力变化&#xff0c;…...

【maven】pom.xml 文件详解

有关 maven 其他配置讲解参考 maven 配置文件 setting.xml 详解 pom.xml 文件是 Maven 项目的核心配置文件&#xff0c;其中包含了项目的元数据、构建配置、依赖管理等信息。以下是一个 pom.xml 文件的主要部分&#xff1a; <?xml version"1.0" encoding"U…...

SpringMVC源码解析——DispatcherServlet初始化

在Spring中&#xff0c;ContextLoaderListener只是辅助功能&#xff0c;用于创建WebApplicationContext类型的实例&#xff0c;而真正的逻辑实现其实是在DispatcherServlet中进行的&#xff0c;DispatcherServlet是实现Servlet接口的实现类。Servlet是一个JAVA编写的程序&#…...

搞定Apache Superset

踩雷了无数次终于解决了Superset的一系列问题 现在是北京时间2023年12月27日&#xff0c;亲测有效。 Superset概述 Apache Superset是一个现代的数据探索和可视化平台。它功能强大且十分易用&#xff0c;可对接各种数据源&#xff0c;包括很多现代的大数据分析引擎&#xff…...

【每日试题】java面试之ssm框架

以下是20道常见的SSM&#xff08;SpringSpring MVCMyBatis&#xff09;面试题目和答案&#xff1a; 什么是SSM框架&#xff1f; SSM是指SpringSpring MVCMyBatis的组合&#xff0c;它是Java Web开发中常用的轻量级框架集合。 介绍一下SSM框架各个组件的作用&#xff1f; Sprin…...

Flutter 疑难杂症集合

一. Flutter集成uni小程序sdk 1. 手机连接电脑测试打开uni小程序没问题&#xff0c;打包成apk后debug编译下的apk也没问题&#xff0c;但就是release编译的apk包打不开小程序。 报错情景&#xff1a;点击后页面会闪现一下黑色的背景&#xff0c;然后又跳转回了点击之前的页面。…...

PHP序列化总结1--序列化和反序列化的基础知识

序列化和反序列化的作用 1.序列化&#xff1a;将对象转化成数组或者字符串的形式 2.反序列化&#xff1a;将数组或字符串的形式转化为对象 为什么要进行序列化 这种数据形式中间会有很多空格&#xff0c;不同人有不同的书写情况&#xff0c;可能还会出现换行的情况 为此为了…...

【Linux】 last 命令使用

last 命令 用于检索和展示系统中用户的登录信息。它从/var/log/wtmp文件中读取记录&#xff0c;并将登录信息按时间顺序列出。 著者 Miquel van Smoorenburg 语法 last [-R] [-num] [ -n num ] [-adiox] [ -f file ] [name...] [tty...]last 命令 -Linux手册页 选项及作用…...

Git 分布式版本控制系统(序章1)

第一章 Git 分布式版本控制系统 为什么学Git? 某些企业面试需要掌握Git&#xff0c;同时&#xff0c;也方便管理自己的Qt项目。 一、Git 客户端下载&#xff08;Windows&#xff09; 下载地址 https://gitee.com/all-about-git#git-%E5%A4%A7%E5%85%A8 二、Git 的特点 分支…...

给WordPress网站添加返回顶部按钮

给WordPress网站底部添加一个按钮&#xff0c;点它就可以现实快速返回到顶部。有两种方法可以现实&#xff0c;一种是通过安装相关插件来实现。另外一种方式就是以纯属代码的方式来实现。 给WordPress网站底部添加一个按钮&#xff0c;点它就可以现实快速返回到顶部。有两种方…...

App Inventor 2 接入短信服务,实现短信验证码功能

发送短信验证码功能一般都是基于短信平台提供的sdk进行调用&#xff0c;这里是基于阿里云短信平台进行的开发&#xff0c;阿里云短信平台接入步骤请点此参考。 App Inventor 2拓展提供的函数如下&#xff1a; 主要提供2个函数&#xff0c;生成随机位数的数字随机码 和 发送短信…...

Linux环境grep搜索方法记录

1 grep grep 命令&#xff0c;用来搜索字符串所在位置&#xff0c;可以具体到不同文件&#xff0c;不同行&#xff1b; 在Linux 下&#xff0c;查看命令释义如下 zhaocubuntu2004:~$ grep --help Usage: grep [OPTION]... PATTERNS [FILE]... Search for PATTERNS in each FI…...

C语言-破解密码

题目描述 密码是我们生活中非常重要的东东&#xff0c;我们的那么一点不能说的秘密就全靠它了。哇哈哈. 接下来渊子要在密码之上再加一套密码&#xff0c;虽然简单但也安全。 假设老王原来一个BBS上的密码为zvbo941987,为了方便记忆&#xff0c;他通过一种算法把这个密码变换…...

ffmpeg 解码文件时的时间戳问题

实时流和普通文件 1 实时流 实时流编码时&#xff0c;我们一般不进行b帧编码&#xff0c;但是文件存储时为了减小大小&#xff0c;会增加b帧&#xff0c;实时流只带了I&#xff0c;P帧&#xff0c;那就会好很多 2 普通文件 很多文件带了b帧&#xff0c;所以要使用解码时间去同…...

Java企业电子招投标系统源代码,支持二次开发,采用Spring cloud框架

在数字化采购领域&#xff0c;企业需要一个高效、透明和规范的管理系统。通过采用Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;我们打造了全过程数字化采购管理平台。该平台具备内外协同的能力&#xff0c;通过待办消息、招标公告、中标公告和信息发布等功能模块…...

[python]基于faster whisper实时语音识别语音转文本

语音识别转文本相信很多人都用过&#xff0c;不管是手机自带&#xff0c;还是腾讯视频都附带有此功能&#xff0c;今天简单说下&#xff1a; faster whisper地址&#xff1a; https://github.com/SYSTRAN/faster-whisperhttps://link.zhihu.com/?targethttps%3A//github.com…...

2023纠结中前行? 2024继续还是放下?

喝下2023年的第一口雪碧&#xff0c;没有想像中的那么期待&#xff0c;甜水&#xff0c;放弃吧&#xff1b;还是吃些水果吧&#xff0c;不行吃块肉、喝两口酒~ 关于生活 挣扎了10几年的一颗牙“终于“掉了&#xff0c;几个月时间都在为新牙努力着&#xff1b;”进了医院就不在…...

原型链补充

1.什么是原型对象 函数的独有属性,他用prototype来表示,可以在函数的prototype上挂载一些公用的属性和方法,供实例化对象来访问。 2.__proto__属性 这个属性每一个对象都有,实例化对象就是通过这个属性,来访问原型对象上的属性和方法的。 3.三者之间的关系 1.在构造函数的原型…...

《Linux Nano命令详解:小而强大的文本编辑器》

《Linux Nano命令详解&#xff1a;小而强大的文本编辑器》 引言&#xff1a; 在Linux系统中&#xff0c;文本编辑是开发和系统管理中不可或缺的一部分。虽然有许多强大的文本编辑器可供选择&#xff0c;但Nano以其简单易用、小巧灵活而备受喜爱。本文将深入探讨Nano命令&…...

系列四、Eureka自我保护

一、Eureka自我保护 1.1、故障现象 保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式&#xff0c;Eureka Server将会尝试保护其服务注册表中的信息&#xff0c;不再删除服务注册表中的数据&#xff0c;也就是不会注销任何微服务。如…...

C++回调函数-实操(二)

回调通常通过函数指针、函数对象&#xff08;仿函数&#xff09;、Lambda 表达式或者 std::function 来实现。 1、函数指针实现回调 这一方法实现回调比较好记&#xff0c;就记住把函数当作参数传给方法&#xff0c;在方法中调用方法。 #include <iostream>// 回调函数…...