kafka 的使用原理及通过spring-kafka 自定义封装包的原理

news2024/11/23 18:51:27

目录:

  • Kafka 封装包接入
    • 1.Kafka 工作原理
    • 2.Spring Kafka 介绍
    • 3. kafka封装包的设计及使用

Kafka 封装包接入

1.Kafaka 工作原理

1).kafka 的定义:

消息队列的两种模式:

在这里插入图片描述
1).点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除) 点对点模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息, 而不是将消息推送到客户端。这个模型的特点是发送到队列的消息被一个且只有一个接收者
接收处理,即使有多个消息监听者也是如此。

2).发布/订阅模式(一对多,数据生产后,推送给所有订阅者) 发布订阅模型则是一个基于推送的消息传送模型。发布订阅模型可以有多种不同的订阅 者,临时订阅者只在主动监听主题时才接收消息,而持久订阅者则监听主题的所有消息,即
使当前订阅者不可用,处于离线状态。

Kafka 的基本介绍:

1).Apache Kafka 是一个开源消息系统,由 Scala 写成。是由 Apache 软件基金会开发的 一个开源消息系统项目。

2).Kafka 最初是由 LinkedIn 公司开发,并于 2011 年初开源。2012 年 10 月从 Apache Incubator 毕业。该项目的目标是为处理实时数据提供一个统一、高通量、低等待的平台。

3).Kafka 是一个分布式消息队列。Kafka 对消息保存时根据 Topic 进行归类,发送消息 者称为 Producer,消息接受者称为 Consumer,此外 kafka 集群有多个 kafka 实例组成,每个 实例(server)
称为 broker。

传统定义:

kafka 是一个分布式基于发布/订阅模式的消息队列(Messge Queue),主要用于大数据实时处理领域。

发布/订阅: 消息的发布不会将消息直接发送给特定的订阅者,而是将发布的消息分为不同的类别,订阅者只接收感兴趣的消息。

最新的定义:

kafka 是一个开源的分布式事件流平台(Event Streaming Platform),被数千件公司用于高性能数据管道、流分析、 数据集成和关键人任务应用。

2).kafka 的应用场景:

缓存/消峰:有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。

在这里插入图片描述

解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

在这里插入图片描述

异步通信:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

3).kafka 的组成:

基础架构:

在这里插入图片描述

1).Producer :消息生产者,就是向 Kafka broker发消息的客户端。

2).Consumer :消息消费者,向 Kafka broker 取消息的客户端。

3).Consumer Group (CG ):消费者组,由多个 consumer组成。 消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个 组内 消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即
消费者组是逻辑上的一个订阅者。

4).Broker :一台 Kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个broker可以容纳多个 topic。

5).Topic:可以理解为一个队列,个 生产者和消费者面向的都是一个 topic。

6).Partition :为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上,个 一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列。
partions主题分区数:kafka通过分区策略,将不同的分区分配在一个集群中的broker上,一般会分散在不同的broker上,当只有一个broker时,所有的分区就只分配到该Broker上。
消息会通过负载均衡发布到不同的分区上,消费者会监测偏移量来获取哪个分区有新数据,从而从该分区上拉取消息数据。分区数越多,在一定程度上会提升消息处理的吞吐量;

7).Replica :副本,一个 topic 的每个分区都有若干个副本,一个 Leader 和若干个 Follower。

8).Leader :每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是 Leader。

9).Follower :每个分区多个副本中的“从”,实时从 Leader 中同步数据,保持和Leader 数据的同步。Leader 发生故障时,某个 Follower 会成为新的 Leader。

10).Offset: 消息位移,表示分区中每条消息的位置信息,是一个单调递增且不变的值

11).Consumer Offset:消费者位移,表征消费者消费进度,每个消费者都有自己的消费者位移。

生产者发送流程:

在消息发送的过程中,涉及到了两个线程 ——main 线程和 Sender 线程。在main线程中创建了一个双端队列 RecordAccumulator。main线程将消息发送给 RecordAccumulator, Sender线程不断从
RecordAccumulator 中拉取消息发送到 Kafka Broker。

在这里插入图片描述

  • 1)producer 先从 zookeeper 的 "/brokers/…/state"节点找到该 partition 的 leader
  • 2)producer 将消息发送给该 leader
  • 3)leader 将消息写入本地 log
  • 4)followers 从 leader pull 消息,写入本地 log 后向 leader 发送 ACK
  • 5)leader 收到所有 ISR 中的 replication 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset)并向 producer 发送 ACK

• batch.size :只有数据积累到batch.size之后,sender才会发送数据。默认16k

• linger.ms :如果数据迟迟未达到batch.size,sender等待linger.time之后就会 发送数据。单位ms,默认值是0ms,表示没有延迟。

acks 应答级别:

在这里插入图片描述

acks=0,生产者发送过来数据就不管了,可靠性差,效率高; acks=1,生产者发送过来数据Leader 应答,可靠性中等,效率中等; acks=-1,生产者发送过来数据Leader 和ISR 队列里面所有Follwer 应答,可靠性高
,效率低;

在生产环境中, acks=0 很少使用;acks=1, 一般用于传输普通日志 , 允许丢个别数据;acks=-1,一般用于传输和钱相关的数据,对可靠性要求比较高的场景 。

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

消费者:

在这里插入图片描述

消费者组定义:消费者使用一个消费者组名(即group.id)来标记自己,topic的每条消息都只会被发送到每个订阅它的消费者组的一个消费者实例上
在这里插入图片描述

一个consumer group可能有若干个consumer实例
对于同一个group而言,topic的每条消息只能被发送到group下的一个consumer实例上
topic消息可以被发送到多个group中

Kafka同时支持基于队列和基于发布/订阅的两种消息引擎模型,事实上Kafka是通过consumer group实现对这两种模型的支持

所有consumer实例都属于相同group—实现基于队列的模型,每条消息只会被一个consumer实例处理
consumer实例都属于不同group—实现基于发布/订阅的模型,极端的情况是每个consumer实例都设置完全不同都group,这样kafka消息就会被广播到所有consumre实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U86RBlDi-1671434814417)(images/img_10.png)]

消费者工作流程:

在这里插入图片描述

consumer需要同时读取多个topic的多个分区消息,若实现并行的消息读取,一种方式是使用多线程,为每个要读取的分区创建一个专有线程去消费,旧版本consumer就是使用这种方式;另一种方式类似于Linux
I/O模型的poll或select,使用一个线程来同时管理多个socket连接,即同时与多个broker实现消息的并行消费,新版本consumer采用这种设计;

消费者初始化流程:

在这里插入图片描述

一旦consumer订阅了topic,所有消费逻辑包括coordinator的协调、消费者组的rebalance以及数据的获取都会在主逻辑poll方法的一次调用中被执行,这样用户很容易使用一个线程来管理consumer I/O操作

对于新版本consumer Kafka
1.0.0而言,是一个双线程Java进程,创建KafkaConsumer的线程被称为用户主线程,同时consumer在后台会创建一个心跳线程。KafkaConsumer的poll方法在用户主线程中运行,这也表明消费者组rebalance、
消息获取、coordinator管理、异步任务结果的处理甚至位移提交等操作都运行在用户主线程中;

漏消费和重复消费:

在这里插入图片描述

重复消费涉及到的相关参数:

  • enable.auto.commit:表示消费者会周期性自动提交消费的offset。默认值true。

  • auto.commit.interval.ms:在enable.auto.commit为true的情况下, 自动提交的间隔。默认值5秒。

  • max.poll.records:单次消费者拉取的最大数据条数,默认值500。

  • max.poll.interval.ms:表示若在阈值时间之内消费者没有消费完上一次poll的消息,consumer
    client会主动向coordinator发起LeaveGroup请求,触发Rebalance;然后consumer重新发送JoinGroup请求。

  • session.timeout.ms:group
    Coordinator检测consumer发生崩溃所需的时间。在这个时间内如果Coordinator未收到Consumer的任何消息,那Coordinator就认为Consumer挂了。默认值10秒。

  • heartbeat.interval.ms:标识Consumer给Coordinator发一个心跳包的时间间隔。heartbeat.interval.ms越小,发的心跳包越多。默认值3秒。

原因1:消费者宕机、重启或者被强行kill进程,导致消费者消费的offset没有提交。
原因2:设置enable.auto.commit为true,如果在关闭消费者进程之前,取消了消费者的订阅,则有可能部分offset没提交,下次重启会重复消费。
原因3:消费后的数据,当offset还没有提交时,Partition就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafka的session timeout.ms时间,那么就会触发reblance重平衡,此时可能存在消费者offset没提交,会导致重平衡后重复消费。

重复消费的解决方法:

提高消费者的处理速度。例如:对消息处理中比较耗时的步骤可通过异步的方式进行处理、利用多线程处理等。在缩短单条消息消费的同时,根据实际场景可将max.poll.interval.ms值设置大一点,避免不必要的Rebalance。可根据实际消息速率适当调小max.poll.records的值。

  • 引入消息去重机制。例如:生成消息时,在消息中加入唯一标识符如消息id等。在消费端,可以保存最近的max.poll.records条消息id到redis或mysql表中,这样在消费消息时先通过查询去重后,再进行消息的处理。

2.Spring Kafka 介绍

1) 相关依赖:

  implementation'org.springframework.kafka:spring-kafka'
  testImplementation'org.springframework.kafka:spring-kafka-test'

2) spring-kafka 的主要参数配置及说明:

spring:
  kafka:
    #kafka 服务地址,可以有多个用,隔开
    bootstrap-servers:localhost: 9002
    # 消費者监听得的 topic 不存在时项目启动不报错
    listener.missinng-topics-fatal: false
    # 在监听容器中运行的线程数:
    listener.concurrency: 10
    # 轮询超时时间:
    listener.pol.timeout: 5000

    # 生产者参数
    producer:
      # 消息发送重试次数
      retries: 0
      # 一个批次可以使用的内存大小:
      batch-size: 16384
      # 设置生产者内存缓存大小:
      buffer-memory: 33554432
      # 同步副本机制:
      acks: 1
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

    consumer:
      group-id:
      # 一次调用poll 返回的最大记录数
      max-poll-recode: 500
      # 是否自动提交偏移量,2.1版本后面默认值为 false ,为了避免出现重复数据和数据丢失,可以把他设置为 false,然后手动提交偏移量
      enable-auto-commmit: false
      # 自动提交的时间间隔: 在spring boot 2.x 版本是值的类型为 Duration 需要符合特定的格式,如1S,1M,2H,5D, enable-auto-commit 为false 情况下该参数不生效
      auto-commit-interval: 1S
      # 该属性指定了消费者在读取一个没有偏移的分区或者偏移量无效的情况下该作何处理:
      # earliest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
      # latest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 默认值
      # none:topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
      auto-offset-reset: earliest
      # 返回的最小字节数,默认为1
      fetch-min-size: 1
      # 最长阻塞时间:
      fetch-max-wait: 500
      #消费者进程 id 
      client-id: 1
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

3) 主要Api:

Configuring Topics

如果你在应用上下文中定义了一个KafkaAdmin的bean,它可以自动向代理添加主题,只需要向每个主题添加NewTopic的bean在应用中的上下文:

        @Bean
        public KafkaAdmin admin(){
        Map<String, Object>  configs=new HashMap();
        configs.put(AdminClientConfig.BOOTSTRAP_SERVER_CONFIG,"localhost:9092");
        reture new KafkaAdmin(configs);
        }
         @Bean
        public NewTopic topic1(){
        return TopicBuilder.name("topic1")
        .partition(1)
        .replicas(1)
        .build();
        }

        @Bean
        public NewTopic topic2(){
        return new NewTopic("topic2",1,(short)1);
        }

在springBoot 项目中,KafkaAdmin 会被自动注册,所以我们只需要NewTopic的bean即可

发送消息 kafkaTemplate:

kafkaTemplate 包装了一个生产者,并提供了方便的方法来发送数据到kafka topic:


      /**
       * Send the data to the default topic with no key or partition.
       * @param data The data.
       * @return a Future for the {@link SendResult}.
       */
        ListenableFuture<SendResult<K, V>>sendDefault(V data);

        /**
         * Send the data to the default topic with the provided key and no partition.
         * @param key the key.
         * @param data The data.
         * @return a Future for the {@link SendResult}.
         */
        ListenableFuture<SendResult<K, V>>sendDefault(K key,V data);

        /**
         * Send the data to the default topic with the provided key and partition.
         * @param partition the partition.
         * @param key the key.
         * @param data the data.
         * @return a Future for the {@link SendResult}.
         */
        ListenableFuture<SendResult<K, V>>sendDefault(Integer partition,K key,V data);

        /**
         * Send the data to the default topic with the provided key and partition.
         * @param partition the partition.
         * @param timestamp the timestamp of the record.
         * @param key the key.
         * @param data the data.
         * @return a Future for the {@link SendResult}.
         * @since 1.3
         */
        ListenableFuture<SendResult<K, V>>sendDefault(Integer partition,Long timestamp,K key,V data);

        /**
         * Send the data to the provided topic with no key or partition.
         * @param topic the topic.
         * @param data The data.
         * @return a Future for the {@link SendResult}.
         */
        ListenableFuture<SendResult<K, V>>send(String topic,V data);

        /**
         * Send the data to the provided topic with the provided key and no partition.
         * @param topic the topic.
         * @param key the key.
         * @param data The data.
         * @return a Future for the {@link SendResult}.
         */
        ListenableFuture<SendResult<K, V>>send(String topic,K key,V data);

        /**
         * Send the data to the provided topic with the provided key and partition.
         * @param topic the topic.
         * @param partition the partition.
         * @param key the key.
         * @param data the data.
         * @return a Future for the {@link SendResult}.
         */
        ListenableFuture<SendResult<K, V>>send(String topic,Integer partition,K key,V data);

以上方法返回一个ListenableFuture<SendResult<K,V>> 监听器

接收消息 :

可以配置MessageListenerContainer 并提供消息监听器或使用@KafkaListener 注解来接收消息:

MessageListenerContainer:

kafka 提供了两个 MessageListenerContainer 来实现

  • KafkaMessageListenerContainer 在一个线程中接收来自所有主题或分区的所有消息
  • ConcurrentMessageListenerContainer 委托给一个或多个KafkaMessageListenerContainer 实例来提供多线程使用

@KafkaListener:

@KafkaListener 注解用于将一个bean 方法指定为监听器容器的监听器

  // 该部分值也可以使用占位符或spel 表达式: topics="{someBean.property}"
@KafkaListener(topics = "chinaclear", groupId = "test")
public void consumerTopic(String msg){
        System.out.println("收到消息:"+msg);
        }


// 使用consumerRecord<?,?> 作为接收消息的参数时除了可有Acknowledgmen 对象外,不能有其他参数
@KafkaListener(topics = "my-replicated-topic", groupId = "test")
public void listenZhugeGroup(ConsumerRecord<String, String> record,Acknowledgment ack){
        String value=record.value();
        System.out.println(value);
        System.out.println(record);
        //手动提交offset
        //ack.acknowledge();
        }   

@KafkaListener 还可以作用在class 类上:
该注解作用于类上时,类中的方法必须用 @KafkaHandler注解,在传递消息时,将使用转换后的消息有效负载类型来确定调用那个方法。方式如下:


@KafkaListener(id = "myId", topics = "myTopic")
public class Myclass {
    @KafkaHandler
    public void listen(String str) {

    }

    @KafkaHandler
    public void listen(Integer integer) {

    }
}

异常处理器KafkaListenerErrorHandler :

KafkaListener中抛出的异常都会经过KafkaListenerErrorHandler 异常处理,spring kafka 提供了ConsumerAwareListenerErrorHandler
的子接口,注册这个类型中的bean 即可:

      @Bean
public ConsumerAwareErrorHandler consumerAwareErrorHandler(){
        return new ConsumerAwareErrorHandler(){

@Override
public void handle(Exception thrownException,ConsumerRecord<?, ?> data,Consumer<?, ?> consumer){
        log.info("Consumer Error Handler receive"+data.toString());
        }};
        }

3. kafka 封装包的设计及使用:

1.引入方式:

   git@github.com:renpengcheng4612/KafkaLearn.git

2.API:

工程内容参考当前工程的 CommonKafka Module

git@github.com:renpengcheng4612/KafkaLearn.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/100557.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Arduino框架下联盛德W801开发环境搭建教程

Arduino框架下联盛德W801开发环境搭建教程联盛德W801拥有自己的SDK集成开发工具&#xff0c;能做到这一点非常令人敬佩和了不起。国内好多芯片厂商都需要依托第三方开发工具集来实现对自己产品的开发。多元化开发方式可以满足不同层次开发人员的需求。对于芯片本身来说&#xf…

机器学习100天(十一):011 回归模型评估指标

机器学习100天,今天讲的是:线性回归评估指标! 一、哪个模型更好? 我们之前已经对房价预测的问题构建了线性模型,并对测试集进行了预测。 如图所示,横坐标是地区人口,纵坐标是房价,红色的点是实际样本分布。 使用不同的算法或策略构建了两个线性回归模型,如图,分别是…

Web3 的开发者,如何评估以及选择调用链上数据的解决方案

FP是链上数据分析平台以及数据处理基础设施&#xff0c;使命是让链上数据分析以及使用随手可得。目前&#xff0c;Footprint 从 22 条公链上收集、解析和清理数据&#xff0c;把无语义以及无序的链上数据&#xff0c;转化成让用户能使用无代码拖放界面、SQL等多种形式构建图表以…

TestStand-用户界面

文章目录简易用户界面全功能用户界面除序列编辑器外&#xff0c;TestStand自带的两类用户界面&#xff0c;分别是SimpleUI&#xff08;简易用户界面&#xff09;及Full-Featured UI&#xff08;全功能用户界面&#xff09;。简易用户界面 简易用户界面的源代码位于< TestSt…

[附源码]计算机毕业设计Python的专业技能认证系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

分享:广电用户服务大数据解决方案

1 方案背景 随着三网融合的深入推进&#xff0c;跨域竞争激烈&#xff0c;电信运营商、互联网企业、硬件设备商以及内容生产商等都将自身定位于视频产业的参与者并获取相应价值&#xff0c;视频服务已经不再成为广电网络运营商的专利&#xff0c;整个视频产业已经开始新一轮颠…

Understanding and Increasing Efficiency of Frank-Wolfe Adversarial Training

AT存在灾难性的过拟合&#xff0c;在训练过程中对抗精度下降&#xff0c;尽管已经提出了改进&#xff0c;但它们增加了训练时间&#xff0c;鲁棒性与多步 AT 相去甚远。我们开发了一个使用 FW 优化 (FW-AT) 进行对抗训练的理论框架&#xff0c;揭示了损失情况与 ℓ∞ FW 攻击的…

vue - vue中的publicPath讲解

vue.config.js里面的publicPath是部署应用包时的基本 URL&#xff1b; 从 Vue CLI 3.3 起baseUrl已被publicPath替代&#xff1b; 如果想要了解vue的环境变量 process.env 可以阅读这篇文章&#xff1a; vue中的process.env.NODE_ENV讲解 1&#xff0c;publicPath publicPath是…

七、ref引用与数组的常用方法

一、ref 引用 1.1、什么是 ref 引用 ref 用来辅助开发者在不依赖于jQuery的情况下&#xff0c;获取 DOM 元素或组件的引用。 每个vue的组件实例上&#xff0c;都包含一个$refs对象&#xff0c;里面存储着对应的 DOM 元素或组件的引用。默认情况下&#xff0c;组件的$refs指向…

语音识别芯片LD3320介绍

语音识别芯片LD3320简介 LD3320 芯片是一款“语音识别”芯片,集成了语音识别处理器和一些外部电路&#xff0c;包括AD、DA 转换器、麦克风接口、声音输出接口等。LD3320不需要外接任何的辅助芯片如Flash、RAM 等&#xff0c;直接集成在LD3320中即可以实现语音识别/声控/人机对…

黑*头条_第6章_kafka及异步通知文章上下架(新版)

黑*头条_第6章_kafka及异步通知文章上下架(新版) 文章目录黑*头条_第6章_kafka及异步通知文章上下架(新版)1)自媒体文章上下架2)kafka概述3)kafka安装配置4)kafka入门5)kafka高可用设计5.1)集群5.2)备份机制(Replication&#xff09;6)kafka生产者详解6.1)发送类型6.2)参数详解…

Linux|Ubuntu-18.04上安装discord(二进制安装)

前言&#xff1a; Discord是由两个沉迷游戏的玩家为了解决游戏种玩家交流问题而开发的一个语音聊天软件&#xff0c;它从游戏社交起家。 起初&#xff0c;Discord被定义为“永远在线的聊天室”&#xff0c;专门为游戏玩家设计&#xff0c;可以简单快捷的加入或退出某个群聊进…

【图像去雾】颜色衰减先验图像去雾【含Matlab源码 2036期】

⛄一、颜色衰减先验去雾算法简介 2015年Zhu等的颜色衰减先验去雾算法利用颜色衰减先验建立有雾图像的景深模型, 采用有监督学习的方式得到模型的参数, 结合大气散射模型得到去雾图像。具体内容如下: 1 大气散射模型 Zhu等的颜色衰减先验去雾算法利用计算机视觉和图形图像领域…

大开眼界的4款电脑软件,其中3款大小不到10M,功能却逆天

闲话少说&#xff0c;直上狠货&#xff0c;大开眼界。 1、Ocam录屏 Ocam是一款完全免费的录屏软件&#xff0c;大小仅有9M&#xff0c;功能却非常强大&#xff0c;界面简洁&#xff0c;操作简单一键录制&#xff0c;4k分辨率视频录制时&#xff0c;即便办公电脑配置不高&#x…

我国海洋油气行业勘探力度加大 整体探明程度有待提高 未来储量产量增长潜力仍很大

1、我国海洋油气资源储量情况 根据观研报告网发布的《2022年中国海洋油气市场分析报告-市场发展监测与发展动向预测》显示&#xff0c;根据全国第四次油气调查数据&#xff0c;海洋石油剩余技术可采储量占中国石油剩余技术可采储量的34%&#xff1b;海洋天然气剩余技术可采储量…

二叉搜索树详解

1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有的节点的值都大于根节点…

执行pip安装时,如何解决:Unknown or unsupported command install

目录 解决方案1&#xff1a;卸载LoadRunner——显然是不可行的 解决方案2&#xff1a;全路径执行pip 解决方案3&#xff1a;镜像 解决方案4&#xff1a;镜像更新 遇到这种情况一般都是因为已经安装了LoadRunner导致电脑上同时安装了多个pip&#xff0c;执行时&#xff0c;系…

LabVIEW如何以编程方式获取克隆VI名称?

LabVIEW如何以编程方式获取克隆VI名称&#xff1f;如何使用克隆VI名称关闭特定的克隆VI&#xff1f; 调用正在运行的VI服务器引用。 放置一个调用节点&#xff0c;然后选择“打开”前面板>>。 使用属性节点检查VI是否为克隆VI>>。 使用属性节点>>克隆名称…

Java安全--CC2

cc2其实都是建立在我们写的基础之上&#xff0c;只不过路走的不一样罢了&#xff0c;我们可以看一下CC2是怎么走的&#xff0c;我用颜色标出了&#xff1a; 其实就是之前都学过的几个类。 前面代码都和CC4一样 public class CC2 {public static void main(String[] args) thro…

2023春招面试题:Java并发相关知识

1.基础知识回顾 1.1 什么是多线程&#xff1f; 在没有线程的年代&#xff0c;在同一个进程中&#xff0c;程序的处理流程都是顺序的&#xff0c;下一个流程的开始必须等待上 一个流程的结束&#xff0c;如果其中某一个流程非常耗时&#xff0c;那么会影响整个流程的处理时间…