【Apache Flink】基于时间和窗口的算子-配置时间特性

news2024/9/23 15:24:54

文章目录

  • 前言
  • 配置时间特性
  • 将时间特性设置为事件时间
  • 时间戳分配器
  • 周期性水位线分配器
      • 创建一个实现AssignerWithPeriodicWatermarks接口的类,目的是为了周期性生成watermark
  • 定点水位线分配器
    • 示例
  • 参考文档

前言

在这里插入图片描述
Apache Flink 它提供了多种类型的时间和窗口概念,使得用户能够进行准确的时间计算。在数据处理任务中,时间的概念是非常重要的,对于一些复杂的实时流处理任务,如事件按时间顺序的聚合、分割和窗口计算,时间更是关键所在。而在这类任务中,选择使用何种时间特性是决定结果准确性的非常重要的一部分。Flink提供了三种时间特性供用户选择:事件时间、处理时间和摄取时间。

在使用Flink进行流处理时,时间窗口的选择也至关重要。Flink的窗口操作可以帮助我们将无限的流数据切分为有限的块,方便我们对每个数据块进行计算。Flink提供了多种窗口类型,包括滑动窗口、滚动窗口、会话窗口和全局窗口,用户可以根据业务需求选择合适的窗口类型。

本文将详细介绍Apache Flink中基于时间和窗口的算子,以及如何配置数据流的时间特性, 深入地理解和使用Flink在实际流式处理任务中进行数据计算的能力。

配置时间特性

在Apache Flink中,时间的概念是极其关键的要素,尤其是当我们处理实时或近实时数据流的时候。Flink提供了三种不同的时间概念,分别用于处理不同的任务和场景。

  1. 事件时间 (Event Time): 事件时间是指数据产生的时间,这个时间通常由事件数据本身携带,例如每个事件的日志行通常都会记录时间戳。在处理可能存在乱序或延迟数据的流计算任务时,事件时间是最常用的处理策略,因为它可以按照事件的发生顺序处理信息,而不是它们被系统接收的顺序。

  2. 处理时间 (Processing Time): 处理时间则是事件在系统中被处理时的系统时间,即事件在引擎处理时的“现在”时间。处理时间对于想要最大性能、毫秒级结果的场景非常适用,比如实时监控或者实时报警这样对处理速度有极高要求的场景。

  3. 摄取时间 (Ingestion Time): 摄取时间属于事件时间和处理时间的一种折衷方案。它是指事件进入Flink系统的时间。如果在一些场合,事件的时间戳无法获取或者不准确,同时又需要一定的事件排序,那么摄取时间就派上用场了。其在源头就分配了时间戳,并在整个处理过程中保留。摄取时间比处理时间语义强,比事件时间性能好。

这三种时间概念的选用,在很大程度上,决定了Flink处理事件的顺序和方式,因此根据实际的场景选择最适合的时间策略是非常重要的。

  1. 事件时间 (Event Time)
  env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

Flink会根据事件所携带的时间戳来处理数据,这就说明了数据是基于何时发生的进行处理的,而不是基于何时被处理的。比如在处理日志分析时,如果日志已经按照事件的发生时间排序,那么事件时间这种设置就会非常有用。

  1. 处理时间 (Processing Time)
   env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);

Flink会按照数据进入系统的时间即系统处理的实时进行处理,无视事件自身的时间戳。比如对于实时监控或者实时报警这样对处理速度有极高要求的场景,处理时间是最适合的。

  1. 摄取时间 (Ingestion Time)
  env.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);

在数据读入Flink时,会自动地获取数据的摄取时间,与处理时间的观念类似但在数据进入系统时就已经赋予了时间。比如在希望事件能在一定程度上按照顺序处理,但又无法获取准确的事件时间时,摄取时间是一个不错的选择。

将时间特性设置为事件时间

在 Flink 中,我们可以指定时间特性为事件时间(Event Time),这是处理一些具体问题(例如延迟数据、重新处理等)的关键。下面是如何在 Flink 中设置时间特性为事件时间的代码示例:
读入一些元素,为它们分配时间戳和水印,并打印出来。分配时间戳和水印是在使用事件时间进行窗口操作等处理时必须要做的。

创建一个执行环境,并设置为事件时间。然后创建一个简单的字符串流,并分配时间戳和水印。最后我们使用了一个时间窗口并打印出了所有的元素。。

import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.functions.timestamps.AscendingTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;

public class EventTimeExample {
    public static void main(String[] args) throws Exception {
        // 创建执行环境
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        
        // 设置时间特性为事件时间
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
        
        // 创建一个数据源,这里我们用的是从集合中获取
        DataStream<String> stream = env.fromElements("element1", "element2", "element3");
        
        // 分配时间戳和水印,这里我们假设通过某种方法获取了一个递增的时间戳
        DataStream<String> withTimestampsAndWatermarks = stream.assignTimestampsAndWatermarks(new AscendingTimestampExtractor<String>() {
            @Override
            public long extractAscendingTimestamp(String element) {
                // 返回当前元素的时间戳,这儿仅作示例,实际应用需要根据具体需求获取
                return System.currentTimeMillis();
            }
        });

        // 对数据进行一些操作,比如过滤,这里的窗口大小为5秒
        withTimestampsAndWatermarks
          .timeWindowAll(Time.seconds(5))
          .apply(new AllWindowFunction<String, Object, TimeWindow>() {
              // 在应用函数中,我们做一些处理,这里简单地打印出所有元素
              public void apply(TimeWindow window, Iterable<String> values, Collector<Object> out) {
                  for (String value : values) {
                      System.out.println(value);
                  }
              }
          });

        // 启动应用
        env.execute("Event Time Example");
    }
}

时间戳分配器

在数据处理系统中,特别是在事件驱动的系统或实时流处理系统中,时间戳分配器是一个非常重要的组件。时间戳分配器的任务就是为每一个事件或数据记录分配一个时间戳,这个时间戳表示该事件发生的时间。

在 Apache Flink 这样的流处理框架中,时间戳分配器通常在数据源(Source)接收到数据时运行,为每一个事件分配一个时间戳。基于事件时间处理的窗口运算、Watermark 生成等流处理任务依赖于这个时间戳。

提供一个基础的时间戳分配器示例,此处假设有一个MapFunction,它将输入的MyEvent转换为一个包含时间戳和事件数据的Tuple2

MyTimestampAssigner实现了AssignerWithPunctuatedWatermarks接口,extractTimestamp()方法用于从数据元素中抽取出时间戳,checkAndGetNextWatermark()方法用于生成水印。在这里每处理一个元素都会调用checkAndGetNextWatermark()生成一个新的水印,这被称为 “punctuated” 模式。若要使用更常见的 “periodic” 模式,需要实现AssignerWithPeriodicWatermarks接口,这会定期(而不是每处理一个元素)生成水印。

public class MyTimestampAssigner implements AssignerWithPunctuatedWatermarks<MyEvent> {

    @Nullable
    @Override
    public Watermark checkAndGetNextWatermark(MyEvent event, long extractTimestamp) {
        return new Watermark(extractTimestamp);
    }

    @Override
    public long extractTimestamp(MyEvent element, long previousElementTimestamp) {
        return element.getCreationTime();
    }
}

然后,可以在流处理中使用这个MyTimestampAssigner来为数据流中的每一个元素分配时间戳:

DataStream<MyEvent> stream = ...
stream.assignTimestampsAndWatermarks(new MyTimestampAssigner());

源数据通常会有一个时间字段,它代表了数据的生成时间。我们可以基于这个时间字段来处理数据,并生成结果。为了让Flink知道每条数据的时间,我们需要自定义Timestamps/Watermarks。以下是一个简单的示例,该代码是在Flink中进行窗口计数的常见工作模式。

在水印生成部分设置了10秒的延迟时间,以处理乱序数据。这意味着,当窗口看到最新的水印时间大于其结束时间时,窗口才会触发进行执行计算。触发后的10秒内,该窗口还会接收更晚到达的数据。这对于处理乱序数据非常有用。

import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.functions.source.SourceFunction.SourceContext;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.api.java.tuple.Tuple2;

public class TimeStampWaterMarkExample {
    public static void main(String[] args) throws Exception {
        // 创建执行环境,设置为事件时间模式
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

        // 元组的第一个参数是一个字符串,第二个参数是一个时间戳
        Tuple2[] data = new Tuple2[]{
                new Tuple2<>("a", 1558430842000L),
                new Tuple2<>("b", 1558430843000L),
                new Tuple2<>("c", 1558430845000L)
        };

        // 添加数据源
        DataStreamSource<Tuple2<String, Long>> dataSource = env.addSource(new SourceFunction<Tuple2<String, Long>>() {
            @Override
            public void run(SourceContext<Tuple2<String, Long>> ctx) throws Exception {
                for (Tuple2<String, Long> datum : data) {
                    ctx.collectWithTimestamp(datum, datum.f1);
                    ctx.emitWatermark(new Watermark(datum.f1 - 1));
                }
                ctx.emitWatermark(new Watermark(Long.MAX_VALUE));
            }

            @Override
            public void cancel() {

            }
        });

        // 添加我们的时间戳分配器和水印生成器
        SingleOutputStreamOperator<Tuple2<String, Long>> timestampOperator = dataSource.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Tuple2<String, Long>>(Time.seconds(10)) {
            @Override
            public long extractTimestamp(Tuple2<String, Long> element) {
                return element.f1;
            }
        });

        // 执行滚动窗口操作
        timestampOperator.keyBy(0)
                .window(TumblingEventTimeWindows.of(Time.seconds(2)))  // 定义滚动窗口
                .apply(new CountWindowFunction())
                .print();

        env.execute("job name");
    }
}

周期性水位线分配器

在流处理系统中,Watermark(水位线)是一种用于处理事件时间乱序的机制。在实时流处理系统中,来自不同源的事件可能以不同的顺序到达。这种顺序的不确定性会给处理系统带来挑战,因为系统必须确定何时所有相关事件都已到达,以便可以进行处理(例如,计算一个5分钟滑动窗口的平均值)。

Watermark就是流处理系统用于处理这种不确定性的一种手段。在Flink中,Watermark是一个特殊的事件或者信号,表示在此时间戳之前的所有事件都已经到达,没有更早的事件会到达。当Watermark t 到达时,说明在时间 t 或者更早的所有数据都已经收到,可以开始处理时间小于或等于 t 的窗口。

周期性水位线 (Periodic Watermark) 是一种定时生成的 Watermark。具体来说,数据流会周期性地调用 getCurrentWatermark() 方法获取新的 Watermark,并且插入到流中。这个周期默认是200ms,也可以通过 ExecutionConfig.setAutoWatermarkInterval(…) 来设置。

在定义 Watermark 生成逻辑时,通常会设置一个允许乱序到达的事件的最大延迟时间。例如,如果最大延迟时间设置为5秒,那么就意味着,Watermark t 只能保证时间戳小于 t-5s 的所有事件都已经到达。换句话说,水位线是滞后于事件时间的,即使水位线是周期性地生成的。

创建一个实现AssignerWithPeriodicWatermarks接口的类,目的是为了周期性生成watermark

BoundedOutOfOrdernessGenerator实现了AssignerWithPeriodicWatermarks接口。extractTimestamp()方法提取了每个元素的时间戳,getCurrentWatermark()则返回新的 watermark。这个实现假设元素可以最多晚3.5秒到达。使用当前最大时间戳减去这个延迟就得到了新的 watermark。这就意味着,即使有延迟的元素到达,只要其时间戳比当前的 watermark 大,它仍然可以用于窗口计算。

 
public class BoundedOutOfOrdernessGenerator implements AssignerWithPeriodicWatermarks<MyEvent> {

    // 最大的乱序容忍度设置为3500毫秒,也就是3.5秒
    private final long maxOutOfOrderness = 3500; 

    // 当前收到的最大的时间戳
    private long currentMaxTimestamp;

    @Override
    // 此方法用于从数据元素中提取时间戳
    public long extractTimestamp(MyEvent element, long previousElementTimestamp) {
        long timestamp = element.getCreationTime();
        // 更新当前收到的最大的时间戳
        currentMaxTimestamp = Math.max(timestamp, currentMaxTimestamp);
        // 返回提取的时间戳
        return timestamp;
    }

    @Nullable
    @Override
    // 此方法返回当前的Watermark,Watermark值为收到的最大时间戳减去乱序容忍度
    public Watermark getCurrentWatermark() {
        return new Watermark(currentMaxTimestamp - maxOutOfOrderness);
    }
}

在流处理中用这个BoundedOutOfOrdernessGenerator为流中的每个元素分配时间戳,并定期生成水位线。

DataStream<MyEvent> stream = ...
// 对流中的元素调用assignTimestampsAndWatermarks函数,传入的参数为BoundedOutOfOrdernessGenerator的实例,这样就完成了对流中元素的时间戳分配和周期性的Watermark生成
stream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessGenerator());

定点水位线分配器

定点水位线分配器(Fixed Watermark Assigner)是一种特定类型的水位线分配器,它生成一个固定的水位线值。它通常在事件的时间戳已经有序且无乱序出现时使用。由于每个元素都有一个时间戳,在这种情况下,水位线可能仅被推进到元素的当前时间戳。在一些特定的应用场景中,这样可能就够用了。

在Apache Flink中,可以使用assignTimestampsAndWatermarks函数结合WatermarkStrategy实现水位线的分配。对于定点水位线分配器,可以创建一个固定的,不变的水位线,例如:

WatermarkStrategy
    .<YourEvent>forMonotonousTimestamps()
    .withTimestampAssigner((event, timestamp) -> event.getTimestamp());

在这个例子中,forMonotonousTimestamps方法会创建一个定点水位线分配器,它将水位线固定在最近被处理的事件的时间戳。withTimestampAssigner方法定义了如何从事件中抽取时间戳。

定点水位线分配器用在那些时间戳严格递增的事件流中,如果在这样的流上使用定点水位线分配器,如果事件到达的顺序与时间戳的顺序不一致(例如,由于网络延迟、机器间的时钟偏移等),就有可能会得到错误的结果。

示例

在这个示例中假定事件是按照时间戳顺序处理的,所以可以有效地使用定点水位线分配器。如果事件的顺序可能会被打乱,那建议使用其他类型的水位线分配器。

创建一个水位线函数,对每一个输入的元素都分配它的时间戳,并产生连续定点的水位线。

public static class MyEvent {
    public long timestamp;  // 定义保存时间戳的变量
    public String data;  // 定义保存数据的变量

    public MyEvent(long timestamp, String data) {  // 构造函数
        this.timestamp = timestamp;
        this.data = data;
    }

    public long getTimestamp() {  // 获取时间戳的接口
        return timestamp;
    }
}

定义了事件类,包括时间戳和数据。

import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;

// 初始化执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

// 配置事件时间特性
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

// 输入的数据流
DataStream<MyEvent> inputStream = env.fromElements(
        new MyEvent(System.currentTimeMillis(), "data1"),
        new MyEvent(System.currentTimeMillis() + 1000, "data2"),
        new MyEvent(System.currentTimeMillis() + 2000, "data3")
);

// 使用水位线分配器给事件分配时间戳和水位线
DataStream<MyEvent> withTimestampsAndWatermarks = inputStream
        .assignTimestampsAndWatermarks(
                WatermarkStrategy.<MyEvent>forMonotonousTimestamps()
                        .withTimestampAssigner((event, timestamp) -> event.getTimestamp())
        );

参考文档

  1. https://nightlies.apache.org/flink/flink-docs-release-1.18/zh/

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

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

相关文章

mysql的医院信息管理系统,数据库增删改查。

基于前端网页和后端服务的&#xff0c;mysql医院信息管理系统。 功能有&#xff1a;登录注册、首页、科室管理、科室列表、医院管理、医生列表、病人管理、护士管理、病房管理、文件管理等等。 并且引入了Echarts图标&#xff0c;可视化查看数据。 源码下载地址 支持&#xff…

Power BI 傻瓜入门 15. DAX功能带来乐趣

本章的内容包括&#xff1a; 了解DAX中的功能使用DAX函数制作定义明确的公式发现哪些DAX函数可以帮助解决复杂的数据计算或操作需求 在第14章中&#xff0c;我将讨论函数如何成为计算表达式中命名公式的一部分。作为提出计算表达式的人&#xff0c;您是为函数提供特定参数的人…

计算机算法分析与设计(21)---回溯法(图着色问题)

文章目录 一、背景知识二、问题转换与描述三、算法讲解3.1 思路分析3.2 状态空间生成树3.3 代码编写 一、背景知识 1. 为地图或其他由不同区域组成的图形着色时&#xff0c;相邻国家/地区不能使用相同的颜色。 我们可能还想使用尽可能少的不同颜色进行填涂。一些简单的“地图”…

第14期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

【QML】vscode安装QML格式化插件方法

1. 安装插件 拓展 > 搜索qml > 找到QML Format >点击安装 2. 配置 打开settings.json文件 ctl shift p&#xff0c;然后搜索settings 修改settings.js内容 {...//添加以下内容// 根据自己电脑安装路径来填写qmlformat.exe的路径&#xff0c;注意转义符"\…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第五章 高效的多线程日志

“日志&#xff08;logging&#xff09;”有两个意思&#xff1a; 1.诊断日志&#xff08;diagnostic log&#xff09;。即log4j、logback、slf4j、glog、g2log、log4cxx、log4cpp、log4cplus、Pantheios、ezlogger等常用日志库提供的日志功能。 2.交易日志&#xff08;trasac…

2023MathorCup高校数模挑战赛B题完整解题代码教程

赛道 B&#xff1a; 电商零售商家需求预测及库存优化问题 问题背景&#xff1a; 电商平台存在着上千个商家&#xff0c;他们会将商品货物放在电商配套的仓库&#xff0c; 电商平台会对这些货物进行统一管理。通过科学的管理手段和智能决策&#xff0c; 大数据智能驱动的供应链…

【C++】多态 ③ ( “ 多态 “ 实现需要满足的三个条件 | “ 多态 “ 的应用场景 | “ 多态 “ 的思想 | “ 多态 “ 代码示例 )

文章目录 一、" 多态 " 实现条件1、" 多态 " 实现需要满足的三个条件2、" 多态 " 的应用场景3、" 多态 " 的思想 二、" 多态 " 代码示例 一、" 多态 " 实现条件 1、" 多态 " 实现需要满足的三个条件 &q…

网络原理的讲解

网络原理 重要性: 网络原理知识 1.工作中非常重要的理论知识,尤其是正在调试一些bug的时候. 2.面试中非常重要的考点. 3.学习中非常关键的难点. 网络原理这里,主要给大家介绍, TCP/IP协议 这里的关键协议. 按照这里的这四层,分别进行介绍(物理层不涉及) 应用层 是和程序猿打…

蓝桥杯 第 2 场算法双周赛 第4题 通关【算法赛】c++ 优先队列 + 小根堆 详解注释版

题目 通关【算法赛】https://www.lanqiao.cn/problems/5889/learning/?contest_id145 问题描述 小蓝最近迷上了一款电玩游戏“蓝桥争霸”。这款游戏由很多关卡和副本组成&#xff0c;每一关可以抽象为一个节点&#xff0c;整个游戏的关卡可以抽象为一棵树形图&#xff0c;每…

asp.net教务管理信息系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio计算机毕业设计

一、源码特点 asp.net 教务管理信息系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言 开发 asp.net教务管理系统 应用技术&a…

基于SSM的高校图书馆设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

真机环境配置教程

1.下载安装包 https://developers.google.com/android/images 2.刷机教程 Xposed精品连载 | 一篇文章彻底搞定安卓刷机与Root 3.配置root

【VTK】关于VTK图像的系列功能

很高兴在雪易的CSDN遇见你 &#xff0c;给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文总结VTK中图像的系列功能&#xff0c;包括图像的导入&#xff08;读取&#xff09;、显示、交互和导出&#xff08;保存&#xff09;等。详细讲解VTK中提供的各种解决思路&#xff…

DreamTexture.js - 基于稳定扩散的3D模型自动纹理化开发包

DreamTexture.js 是面向 three.js 开发者的 3D 模型纹理自动生成与设置开发包&#xff0c;可以为 webGL 应用增加 3D 模型的快速自动纹理化能力&#xff0c;官方下载地址&#xff1a;DreamTexture.js自动纹理化开发包 。 图一为原始模型, 图二图三为贴图后的模型。提示词&#…

PN8370 超低待机功耗准谐振原边反馈交直流转换器 适用于5V 2A的充电器芯片

PN8370集成超低待机功耗准谐振原边控制器及650V高雪崩能力智能功率MOSFET&#xff0c;用于高性能、外围元器件精简的充电器、适配器和内置电源。 PN8370为原边反馈工作模式,可省略光耦和TL431。内置高压启动电路,可实现芯片空载损耗(230VAC)小于30mW。在恒压模式&#xff0c;采…

FindDiff_Qt找不同项目

文章目录 项目简介源代码widget.hwidget.cppwidget.ui配置文件找不同.json 项目简介 开发平台 win10Qt6.6msvc2022 简介 微信上有一些好玩的游戏, 找不同一种比较轻松有趣的游戏,也曾经在街机上被坑过N币, 玩了几次后,发现还是太难了,于是开始截屏放大,慢慢找,再然后就发展到截…

2023软件测试高频面试题

前言 今天&#xff0c;我们来整理与解析一些比较高频的测试行业面试题&#xff0c;大家可以通过面试题内的一些解析&#xff0c;再结合自己的真实工作经验来进行答题思路的提取、整理。 友情提示&#xff1a;硬背答案虽可&#xff0c;但容易翻车哦。 同时&#xff0c;我也准备…

【蓝桥杯选拔赛真题04】C++计算24数字游戏 青少年组蓝桥杯C++选拔赛真题 STEMA比赛真题解析

目录 C/C++计算24数字游戏 一、题目要求 1、编程实现 2、输入输出 二、算法分析

7、电路综合-基于简化实频的SRFT微带线巴特沃兹低通滤波器设计

7、电路综合-基于简化实频的SRFT微带线巴特沃兹低通滤波器设计 5、电路综合-超酷-基于S11参数直接综合出微带线电路图中已经介绍了如何从传输函数或S参数综合出电路图。 24、基于原型的切比雪夫低通滤波器设计理论&#xff08;插入损耗法&#xff09;中介绍了使用集总参数元件…