Flink (七): DataStream API (四) Watermarks
1. Event Time and Processing Time
1. 1 处理时间(Processing time)
处理时间是指执行相应操作的机器的系统时间。当流处理程序基于处理时间运行时,所有基于时间的操作(如时间窗口)将使用执行相应算子的机器的系统时钟。一个每小时的处理时间窗口将包括在系统时钟指示整点时,所有到达该算子的记录。例如,如果一个应用程序在上午9:15开始运行,第一个每小时的处理时间窗口将包括在9:15到10:00之间处理的事件,接下来的窗口将包括在10:00到11:00之间处理的事件,依此类推。处理时间是最简单的时间概念,不需要在流和机器之间进行协调。它提供了最佳的性能和最低的延迟。然而,在分布式和异步环境中,处理时间无法提供确定性,因为它容易受到记录到达速度(例如来自消息队列)、记录在系统中流动速度以及故障(计划的或其他类型的)等因素的影响。
1.2 事件时间(Event time)
事件时间是每个单独事件发生在其产生设备上的时间。这个时间通常在记录进入 Flink 之前就已嵌入,事件的时间戳可以从每条记录中提取。在事件时间中,时间的进度取决于数据,而不是任何时钟。事件时间程序必须指定如何生成 事件时间水印(Event Time Watermarks)。在理想的情况下,事件时间处理将产生完全一致和确定的结果,无论事件何时到达,或它们的顺序如何。然而,除非事件已知按顺序到达(按时间戳),否则事件时间处理会因为等待乱序事件而产生一定的延迟。由于只能等待有限的时间,这对事件时间应用程序的及时性会造成影响。
假设所有数据都已到达,事件时间操作将按预期行为,并在处理乱序或迟到事件时,或者在重新处理历史数据时,产生正确和一致的结果。例如,一个每小时的事件时间窗口将包含所有事件时间戳落在该小时内的记录,无论它们到达的顺序如何,或者它们何时被处理。
2. Event Time and Watermarks
注意:Flink 实现了许多来自数据流模型(Dataflow Model)的技术。关于事件时间和水印的详细介绍,请参考以下文章:
- Tyler Akidau 的《Streaming 101》
- 《The Dataflow Model》论文
支持事件时间的流处理器需要一种衡量事件时间进度的方法。例如,一个构建按小时划分的窗口的窗口算子,需要在事件时间超过一个小时的结束时得到通知,以便该算子可以关闭当前的窗口。
事件时间可以独立于处理时间。例如,在一个程序中,算子的当前事件时间可能会略微滞后于处理时间(考虑到接收事件的延迟),但两者以相同的速度推进。另一方面,另一个流处理程序可能通过快速推进已经缓存在 Kafka 主题(或其他消息队列)中的一些历史数据,仅用几秒钟就能跨越几周的事件时间。在 Flink 中,用来衡量事件时间进度的机制是水印(Watermarks)。水印作为数据流的一部分流动,并携带一个时间戳 t。一个 Watermark(t) 表示事件时间已经到达时间 t,这意味着在该流中不会再有时间戳 t' <= t 的元素(即事件时间戳小于或等于水印的事件)。
下图展示了带有(逻辑)时间戳的事件流,并且水印与事件一起流动。在这个例子中,事件是按时间戳顺序排列的,这意味着水印只是流中的定期标记。
水印对于乱序流至关重要,正如下图所示,其中事件并未按时间戳排序。一般来说,水印是一个声明,表示在流中的某一点,所有时间戳小于等于某个值的事件都应该已经到达。一旦水印到达算子,算子就可以将其内部的事件时间时钟推进到水印的时间值。
请注意,事件时间是由新创建的流元素继承的,继承自产生这些元素的事件,或者继承自触发这些元素创建的水印。
2.1 Watermarks in Parallel Streams
水印是在源函数处或紧接着源函数之后生成的。每个源函数的并行子任务通常会生成自己的水印。这些水印定义了该并行源的事件时间。随着水印在流处理程序中流动,它们会推进到达算子处的事件时间。每当一个算子推进其事件时间时,它会为下游的后续算子生成一个新的水印。
一些算子会消费多个输入流;例如,union 算子,或者在 keyBy(…) 或 partition(…) 函数之后的算子。此类算子的当前事件时间是其输入流事件时间的最小值。当其输入流更新事件时间时,算子的事件时间也会更新。
下图展示了事件和水印在并行流中流动的示例,以及算子如何追踪事件时间。
3. Lateness
某些元素可能会违反水印条件,即使在 Watermark(t) 发生之后,仍然会有时间戳 t' <= t 的元素到达。事实上,在许多现实世界的应用中,某些元素可能会延迟,这使得无法指定一个时间点,在此之前所有具有特定事件时间戳的元素都已经到达。此外,即使迟到情况可以被处理,水印延迟过多通常也是不理想的,因为这会导致事件时间窗口的延迟过大。
因此,流处理程序可能会明确地预期某些 迟到元素。迟到元素是指在事件时间(由水印表示)已经超过该迟到元素时间戳的时间后到达的元素。 对于窗口中如何处理迟到元素,可以参考文章Flink (六):DataStream API (三) 窗口 对于迟到元素处理的一节
4. 生成 Watermark
4.1 Watermark 策略简介
为了使用事件时间语义,Flink 应用程序需要知道事件时间戳对应的字段,意味着数据流中的每个元素都需要拥有可分配的事件时间戳。其通常通过使用 TimestampAssigner
API 从元素中的某个字段去访问/提取时间戳。
时间戳的分配与 watermark 的生成是齐头并进的,其可以告诉 Flink 应用程序事件时间的进度。其可以通过指定 WatermarkGenerator
来配置 watermark 的生成方式。
使用 Flink API 时需要设置一个同时包含 TimestampAssigner
和 WatermarkGenerator
的 WatermarkStrategy
。WatermarkStrategy
工具类中也提供了许多常用的 watermark 策略,并且用户也可以在某些必要场景下构建自己的 watermark 策略。WatermarkStrategy 接口如下:
public interface WatermarkStrategy<T> extends TimestampAssignerSupplier<T>, WatermarkGeneratorSupplier<T>{/*** 根据策略实例化一个可分配时间戳的 {@link TimestampAssigner}。*/@OverrideTimestampAssigner<T> createTimestampAssigner(TimestampAssignerSupplier.Context context);/*** 根据策略实例化一个 watermark 生成器。*/@OverrideWatermarkGenerator<T> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context);
}
如上所述,通常情况下,你不用实现此接口,而是可以使用 WatermarkStrategy
工具类中通用的 watermark 策略,或者可以使用这个工具类将自定义的 TimestampAssigner
与 WatermarkGenerator
进行绑定。例如,你想要要使用有界无序(bounded-out-of-orderness)watermark 生成器和一个 lambda 表达式作为时间戳分配器,那么可以按照如下方式实现:
WatermarkStrategy.<Tuple2<Long, String>>forBoundedOutOfOrderness(Duration.ofSeconds(20)).withTimestampAssigner((event, timestamp) -> event.f0);
其中 TimestampAssigner
的设置与否是可选的,大多数情况下,可以不用去特别指定。例如,当使用 Kafka 或 Kinesis 数据源时,你可以直接从 Kafka/Kinesis 数据源记录中获取到时间戳。
4.2 使用 Watermark 策略
WatermarkStrategy
可以在 Flink 应用程序中的两处使用,第一种是直接在数据源上使用,第二种是直接在非数据源的操作之后使用。
第一种方式相比会更好,因为数据源可以利用 watermark 生成逻辑中有关分片/分区(shards/partitions/splits)的信息。使用这种方式,数据源通常可以更精准地跟踪 watermark,整体 watermark 生成将更精确。直接在源上指定 WatermarkStrategy
意味着你必须使用特定数据源接口,仅当无法直接在数据源上设置策略时,才应该使用第二种方式(在任意转换操作之后设置 WatermarkStrategy
):
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();DataStream<MyEvent> stream = env.readFile(myFormat, myFilePath, FileProcessingMode.PROCESS_CONTINUOUSLY, 100,FilePathFilter.createDefaultFilter(), typeInfo);DataStream<MyEvent> withTimestampsAndWatermarks = stream.filter( event -> event.severity() == WARNING ).assignTimestampsAndWatermarks(<watermark strategy>);withTimestampsAndWatermarks.keyBy( (event) -> event.getGroup() ).window(TumblingEventTimeWindows.of(Time.seconds(10))).reduce( (a, b) -> a.add(b) ).addSink(...);
使用 WatermarkStrategy
去获取流并生成带有时间戳的元素和 watermark 的新流时,如果原始流已经具有时间戳或 watermark,则新指定的时间戳分配器将覆盖原有的时间戳和 watermark。
4.3 处理空闲数据源
如果数据源中的某一个分区/分片在一段时间内未发送事件数据,则意味着 WatermarkGenerator
也不会获得任何新数据去生成 watermark。我们称这类数据源为空闲输入或空闲源。在这种情况下,当某些其他分区仍然发送事件数据的时候就会出现问题。由于下游算子 watermark 的计算方式是取所有不同的上游并行数据源 watermark 的最小值,则其 watermark 将不会发生变化。
为了解决这个问题,你可以使用 WatermarkStrategy
来检测空闲输入并将其标记为空闲状态。WatermarkStrategy
为此提供了一个工具接口:
WatermarkStrategy.<Tuple2<Long, String>>forBoundedOutOfOrderness(Duration.ofSeconds(20)).withIdleness(Duration.ofMinutes(1));
4.4 Watermark alignment
在前一段中,我们讨论了当分片/分区/分片或源处于空闲状态并可能导致水印停滞的情况。另一方面,某个分片/分区/分片或源可能处理记录的速度非常快,从而使其水印相对其他部分更快地推进。单独来看,这本身并不是一个问题。然而,对于那些使用水印来发送数据的下游算子来说,这可能会成为一个问题。
在这种情况下,与空闲源相反,某些下游算子(例如带窗口的连接或聚合操作)的水印可以推进。然而,这些算子可能需要缓冲来自快速输入的过多数据,因为所有输入流的最小水印会被滞后的输入流拖慢。因此,来自快速输入的所有记录必须缓存在下游算子的状态中,这可能会导致算子状态的不可控增长。
为了解决这个问题,可以启用水印对齐,这样可以确保没有源/分片/分区/分片的水印推进得过快。您可以为每个源单独启用对齐:
WatermarkStrategy.<Tuple2<Long, String>>forBoundedOutOfOrderness(Duration.ofSeconds(20)).withWatermarkAlignment("alignment-group-1", Duration.ofSeconds(20), Duration.ofSeconds(1));
在启用水印对齐时,您需要告诉 Flink 哪个组应该包含该源。您可以通过提供一个标签(例如:alignment-group-1
)来将所有共享该标签的源绑定在一起。此外,您还需要告诉 Flink 所有属于该组的源的当前最小水印之间的最大偏移量。第三个参数描述了当前最大水印应该多久更新一次。频繁更新的缺点是会产生更多的 RPC 消息在任务管理器(TM)和作业管理器(JM)之间传递。
为了实现水印对齐,Flink 会暂停消费来自产生过早水印的源/任务的记录,同时继续从其他源/任务读取记录,这些记录能够推动合并水印向前推进,从而解除较快源的阻塞。
4.5 自定义 WatermarkGenerator
TimestampAssigner
是一个可以从事件数据中提取时间戳字段的简单函数,我们无需详细查看其实现。但是 WatermarkGenerator
的编写相对就要复杂一些了,WatermarkGenerator 接口代码如下:
/*** {@code WatermarkGenerator} 可以基于事件或者周期性的生成 watermark。** <p><b>注意:</b> WatermarkGenerator 将以前互相独立的 {@code AssignerWithPunctuatedWatermarks} * 和 {@code AssignerWithPeriodicWatermarks} 一同包含了进来。*/
@Public
public interface WatermarkGenerator<T> {/*** 每来一条事件数据调用一次,可以检查或者记录事件的时间戳,或者也可以基于事件数据本身去生成 watermark。*/void onEvent(T event, long eventTimestamp, WatermarkOutput output);/*** 周期性的调用,也许会生成新的 watermark,也许不会。** <p>调用此方法生成 watermark 的间隔时间由 {@link ExecutionConfig#getAutoWatermarkInterval()} 决定。*/void onPeriodicEmit(WatermarkOutput output);
}
watermark 的生成方式本质上是有两种:周期性生成和标记生成。
周期性生成器通常通过 onEvent()
观察传入的事件数据,然后在框架调用 onPeriodicEmit()
时发出 watermark。
标记生成器将查看 onEvent()
中的事件数据,并等待检查在流中携带 watermark 的特殊标记事件或打点数据。当获取到这些事件数据时,它将立即发出 watermark。通常情况下,标记生成器不会通过 onPeriodicEmit()
发出 watermark。
4.5.1 自定义周期性 Watermark 生成器
周期性生成器会观察流事件数据并定期生成 watermark(其生成可能取决于流数据,或者完全基于处理时间)。
生成 watermark 的时间间隔(每 n 毫秒)可以通过 ExecutionConfig.setAutoWatermarkInterval(...)
指定。每次都会调用生成器的 onPeriodicEmit()
方法,如果返回的 watermark 非空且值大于前一个 watermark,则将发出新的 watermark。
如下是两个使用周期性 watermark 生成器的简单示例。注意:Flink 已经附带了 BoundedOutOfOrdernessWatermarks
,它实现了 WatermarkGenerator
,其工作原理与下面的 BoundedOutOfOrdernessGenerator
相似
/*** 该 watermark 生成器可以覆盖的场景是:数据源在一定程度上乱序。* 即某个最新到达的时间戳为 t 的元素将在最早到达的时间戳为 t 的元素之后最多 n 毫秒到达。*/
public class BoundedOutOfOrdernessGenerator implements WatermarkGenerator<MyEvent> {private final long maxOutOfOrderness = 3500; // 3.5 秒private long currentMaxTimestamp;@Overridepublic void onEvent(MyEvent event, long eventTimestamp, WatermarkOutput output) {currentMaxTimestamp = Math.max(currentMaxTimestamp, eventTimestamp);}@Overridepublic void onPeriodicEmit(WatermarkOutput output) {// 发出的 watermark = 当前最大时间戳 - 最大乱序时间output.emitWatermark(new Watermark(currentMaxTimestamp - maxOutOfOrderness - 1));}}/*** 该生成器生成的 watermark 滞后于处理时间固定量。它假定元素会在有限延迟后到达 Flink。*/
public class TimeLagWatermarkGenerator implements WatermarkGenerator<MyEvent> {private final long maxTimeLag = 5000; // 5 秒@Overridepublic void onEvent(MyEvent event, long eventTimestamp, WatermarkOutput output) {// 处理时间场景下不需要实现}@Overridepublic void onPeriodicEmit(WatermarkOutput output) {output.emitWatermark(new Watermark(System.currentTimeMillis() - maxTimeLag));}
}
4.5.2 自定义标记 Watermark 生成器
标记 watermark 生成器观察流事件数据并在获取到带有 watermark 信息的特殊事件元素时发出 watermark。
如下是实现标记生成器的方法,当事件带有某个指定标记时,该生成器就会发出 watermark:
public class PunctuatedAssigner implements WatermarkGenerator<MyEvent> {@Overridepublic void onEvent(MyEvent event, long eventTimestamp, WatermarkOutput output) {if (event.hasWatermarkMarker()) {output.emitWatermark(new Watermark(event.getWatermarkTimestamp()));}}@Overridepublic void onPeriodicEmit(WatermarkOutput output) {// onEvent 中已经实现}
}
4.6 Watermark 策略与 Kafka 连接器
当使用 Apache Kafka 连接器作为数据源时,每个 Kafka 分区可能有一个简单的事件时间模式(递增的时间戳或有界无序)。然而,当使用 Kafka 数据源时,多个分区常常并行使用,因此交错来自各个分区的事件数据就会破坏每个分区的事件时间模式(这是 Kafka 消费客户端所固有的)。
在这种情况下,你可以使用 Flink 中可识别 Kafka 分区的 watermark 生成机制。使用此特性,将在 Kafka 消费端内部针对每个 Kafka 分区生成 watermark,并且不同分区 watermark 的合并方式与在数据流 shuffle 时的合并方式相同。
例如,如果每个 Kafka 分区中的事件时间戳严格递增,则使用单调递增时间戳分配器按分区生成的 watermark 将生成完美的全局 watermark。注意,我们在示例中未使用 TimestampAssigner
,而是使用了 Kafka 记录自身的时间戳。
下图展示了如何使用单 kafka 分区 watermark 生成机制,以及在这种情况下 watermark 如何通过 dataflow 传播。
KafkaSource<String> kafkaSource = KafkaSource.<String>builder().setBootstrapServers(brokers).setTopics("my-topic").setGroupId("my-group").setStartingOffsets(OffsetsInitializer.earliest()).setValueOnlyDeserializer(new SimpleStringSchema()).build();DataStream<String> stream = env.fromSource(kafkaSource, WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(20)), "mySource");
4.7 算子处理 Watermark 的方式
一般情况下,在将 watermark 转发到下游之前,需要算子对其进行触发的事件完全进行处理。例如,WindowOperator
将首先计算该 watermark 触发的所有窗口数据,当且仅当由此 watermark 触发计算进而生成的所有数据被转发到下游之后,其才会被发送到下游。换句话说,由于此 watermark 的出现而产生的所有数据元素都将在此 watermark 之前发出。
相同的规则也适用于 TwoInputStreamOperator
。但是,在这种情况下,算子当前的 watermark 会取其两个输入的最小值。
5. 内置 Watermark 生成器
5.1 单调递增时间戳分配器
周期性 watermark 生成方式的一个最简单特例就是你给定的数据源中数据的时间戳升序出现。在这种情况下,当前时间戳就可以充当 watermark,因为后续到达数据的时间戳不会比当前的小。
注意:在 Flink 应用程序中,如果是并行数据源,则只要求并行数据源中的每个单分区数据源任务时间戳递增。例如,设置每一个并行数据源实例都只读取一个 Kafka 分区,则时间戳只需在每个 Kafka 分区内递增即可。Flink 的 watermark 合并机制会在并行数据流进行分发(shuffle)、联合(union)、连接(connect)或合并(merge)时生成正确的 watermark。
WatermarkStrategy.forMonotonousTimestamps();
5.2 数据之间存在最大固定延迟的时间戳分配器
另一个周期性 watermark 生成的典型例子是,watermark 滞后于数据流中最大(事件时间)时间戳一个固定的时间量。该示例可以覆盖的场景是你预先知道数据流中的数据可能遇到的最大延迟,例如,在测试场景下创建了一个自定义数据源,并且这个数据源的产生的数据的时间戳在一个固定范围之内。Flink 针对上述场景提供了 boundedOutfordernessWatermarks
生成器,该生成器将 maxOutOfOrderness
作为参数,该参数代表在计算给定窗口的结果时,允许元素被忽略计算之前延迟到达的最长时间。其中延迟时长就等于 t - t_w
,其中 t
代表元素的(事件时间)时间戳,t_w
代表前一个 watermark 对应的(事件时间)时间戳。如果 lateness > 0
,则认为该元素迟到了,并且在计算相应窗口的结果时默认会被忽略
WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10));
相关文章:
Flink (七): DataStream API (四) Watermarks
1. Event Time and Processing Time 1. 1 处理时间(Processing time) 处理时间是指执行相应操作的机器的系统时间。当流处理程序基于处理时间运行时,所有基于时间的操作(如时间窗口)将使用执行相应算子的机器的系统时…...
卷积神经05-GAN对抗神经网络
卷积神经05-GAN对抗神经网络 使用Python3.9CUDA11.8Pytorch实现一个CNN优化版的对抗神经网络 简单的GAN图片生成 CNN优化后的图片生成 优化模型代码对比 0-核心逻辑脉络 1)Anacanda使用CUDAPytorch2)使用本地MNIST进行手写图片训练3)…...
【原创】大数据治理入门(2)《提升数据质量:质量评估与改进策略》入门必看 高赞实用
提升数据质量:质量评估与改进策略 引言:数据质量的概念 在大数据时代,数据的质量直接影响到数据分析的准确性和可靠性。数据质量是指数据在多大程度上能够满足其预定用途,确保数据的准确性、完整性、一致性和及时性是数据质量的…...
GLM: General Language Model Pretraining with Autoregressive Blank Infilling论文解读
论文地址:https://arxiv.org/abs/2103.10360 参考:https://zhuanlan.zhihu.com/p/532851481 GLM混合了自注意力和masked注意力,而且使用了2D位置编码。第一维的含义是在PartA中的位置,如5 5 5。第二维的含义是在Span内部的位置&a…...
总结SpringBoot项目中读取resource目录下的文件多种方法
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目…...
云原生第四次作业
下载 [rootopenEuler-1 ~]# wget https://archive.apache.org/dist/httpd/httpd-2.4.46.tar.gz 压缩 配置实验环境 [rootopenEuler-1 httpd-2.4.46]# yum -y install apr apr-devel cyrus-sasl-devel expat-devel libdb-devel openldap-devel apr-util-devel apr-util pcre-d…...
day10_Structured Steaming
文章目录 Structured Steaming一、结构化流介绍(了解)1、有界和无界数据2、基本介绍3、使用三大步骤(掌握)4.回顾sparkSQL的词频统计案例 二、结构化流的编程模型(掌握)1、数据结构2、读取数据源2.1 File Source2.2 Socket Source…...
设计模式-工厂模式/抽象工厂模式
工厂模式 定义 定义一个创建对象的接口,让子类决定实列化哪一个类,工厂模式使一个类的实例化延迟到其子类; 工厂方法模式是简单工厂模式的延伸。在工厂方法模式中,核心工厂类不在负责产品的创建,而是将具体的创建工作…...
【算法学习】——整数划分问题详解(动态规划)
🧮整数划分问题是一个较为常见的算法题,很多问题从整数划分这里出发,进行包装,形成新的题目,所以完全理解整数划分的解决思路对于之后的进一步学习算法是很有帮助的。 「整数划分」通常使用「动态规划」解决࿰…...
【新教程】Ubuntu 24.04 单节点安装slurm
背景 网上教程老旧,不适用。 详细步骤 1、安装slurm sudo apt install slurm-wlm slurm-wlm-doc -y检查是否安装成功: slurmd --version如果得到slurm-wlm 23.11.4,表明安装成功。 2、配置slurm。 使用命令: sudo vi /etc/s…...
window下用vim
Windows 默认不支持 vim 命令,需要手动安装后才能使用。以下是解决方案: 1. 安装 Vim 编辑器 方法 1:通过 Scoop 或 Chocolatey 安装 使用 Scoop: 安装 Scoop(如果尚未安装):iwr -useb get.sco…...
citrix netscaler13.1 重写负载均衡响应头(基础版)
在 Citrix NetScaler 13.1 中,Rewrite Actions 用于对负载均衡响应进行修改,包括替换、删除和插入 HTTP 响应头。这些操作可以通过自定义策略来完成,帮助你根据需求调整请求内容。以下是三种常见的操作: 1. Replace (替换响应头)…...
使用PWM生成模式驱动BLDC三相无刷直流电机
引言 在 TI 的无刷直流 (BLDC) DRV8x 产品系列使用的栅极驱动器应用中,通常使用一些控制模式来切换MOSFET 开关的输出栅极。这些控制模式包括:1x、3x、6x 和独立脉宽调制 (PWM) 模式。 不过,DRV8x 产品系列(例如 DRV8311&…...
常见的php框架有哪几个?
一直以来,PHP作为一种广泛使用的编程语言,拥有着许多优秀的框架来帮助开发人员快速构建稳定的Web应用程序。本文降为大家介绍几种常见的PHP的主流框架,以及它们相关的特点和使用场景。如有问题,欢迎指正! 1.Laravel&a…...
机器学习(2):线性回归Python实现
1 概念回顾 1.1 模型假设 线性回归模型假设因变量y yy与自变量x xx之间的关系可以用以下线性方程表示: y β 0 β 1 ⋅ X 1 β 2 ⋅ X 2 … β n ⋅ X n ε y 是因变量 (待预测值);X1, X2, ... Xn 是自变量(特征)β0, β1,…...
Unity-Mirror网络框架-从入门到精通之RigidbodyPhysics示例
文章目录 前言示例一、球体的基础配置二、三个球体的设置差异三、示例意图LatencySimulation前言 在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。本系列文章将为读者提供对Mirror网络框架的深入了解,涵盖从基础到高级的多个主题。Mirror是一个用于Unity的开…...
【Unity-Animator】通过 StateMachineBehaviour 实现回调
StateMachineBehaviour 简介 StateMachineBehaviour是一个基类,所有状态脚本都派生自该类。它可以在状态机进入、退出或更新状态时执行代码,而无需编写自己的逻辑来测试和检测状态的变化。这使得开发者可以更方便地处理状态转换时的逻辑,例…...
并行服务、远程SSH无法下载conda,报错404
原下载代码无效,报错404 wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh 使用下面代码下载 wget --user-agent"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12…...
cuquantum 简介
1. 关于 cuquantum 概述 官方文档: https://docs.nvidia.com/cuda/cuquantum/latest/appliance/overview.html#prerequisites NVIDIA 的 cuQuantum 是一个专门用于量子计算的高性能库,旨在加速量子电路的模拟和量子算法的执行。cuQuantum 提供了一系列…...
小程序如何引入腾讯位置服务
小程序如何引入腾讯位置服务 1.添加服务 登录 微信公众平台 注意:小程序要企业版的 第三方服务 -> 服务 -> 开发者资源 -> 开通腾讯位置服务 在设置 -> 第三方设置 中可以看到开通的服务,如果没有就在插件管理中添加插件 2.腾讯位置服务…...
【react】使用antd Table渲染数据遇到的报错问题
记录自己在开发过程中遇到的报错问题: 目录 原本写法:错误分析:解决方案: 原本写法: render: (text) > {console.log(text, "111111text");console.log(typeof text, "111111text");return t…...
55_OpenResty开发入门
Nginx编程需要用到Lua语言,因此我们必须先学习Lua的基本语法。Nginx本身也是C语言开发,因此也允许基于Lua做拓展。多级缓存的实现离不开Nginx编程,而Nginx编程又离不开OpenResty。 1.OpenResty概述 OpenResty是一款基于NGINX和LuaJIT的Web平台。通过Lua扩展NGINX实现的可伸…...
(即插即用模块-Attention部分) 四十四、(ICIP 2022) HWA 半小波注意力
文章目录 1、Half Wavelet Attention2、代码实现 paper:HALFWAVELET ATTENTION ON M-NET FOR LOW-LIGHT IMAGE ENHANCEMENT Code:https://github.com/FanChiMao/HWMNet 1、Half Wavelet Attention 传统的图像增强方法主要关注图像在空间域的特征信息&am…...
链家房价数据爬虫和机器学习数据可视化预测
完整源码项目包获取→点击文章末尾名片!...
全网首发:编译libssh,产生类似undefined reference to `EVP_aes_256_ctr@OPENSSL_1_1_0‘的大量错误
具体错误 前面和后面的: /opt/linux/x86-arm/aarch64-mix210-linux/host_bin/../lib/gcc/aarch64-linux-gnu/7.3.0/../../../../aarch64-linux-gnu/bin/ld: warning: libcrypto.so.1.1, needed by ../lib/libssh.so.4.10.1, not found (try using -rpath or -rpat…...
springboot 集成javaFx 两个面板之间如何进行跳转
1.创建两个面板 可参考博主的 java8 springboot 集成javaFx 实现一个客户端程序 文章来实现 2.完善代码 以下是博主创建的两个模板 博主在这里实现的是登录跳转功能,注意:这里登录按钮的触发实现方式做了以下小小的改动,也可根据自己的习惯来处理 相较第一篇文章,博主在Lo…...
vue-cli项目配置使用unocss
在了解使用了Unocss后,就完全被它迷住了。接手过的所有项目都配置使用了它,包括一些旧项目,也跟同事分享了使用Unocss的便捷性。 这里分享一下旧项目如何配置和使用Unocss的,项目是vue2vue-cli构建的,node<20平常开…...
ASP.NET Core - IStartupFilter 与 IHostingStartup
ASP.NET Core - IStartupFilter 与 IHostingStartup 1. IStartupFilter2 IHostingStartup2.5.1 创建外部程序集2.5.2 激活外部程序集 1. IStartupFilter 上面讲到的方式虽然能够根据不同环境将Startup中的启动逻辑进行分离,但是有些时候我们还会可以根据应用中的功能…...
学习ASP.NET Core的身份认证(基于JwtBearer的身份认证5)
用户在前端页面登录成功后会从服务端获取Token,后续调用服务器的服务接口时都得带着Token,否则就会验证失败。之前使用postman测试的时候,获取Token后再调用其它服务都是人工将Token添加到Header中,网页中没法这么做,只…...
【Vue】let、const、var的区别、适用场景
let、const、var,有哪些区别,适用场景 var 特点: var 是 JavaScript 中最传统的变量声明方式。具有函数作用域,即在函数内声明的 var 变量,在整个函数内都可以访问。变量提升:使用 var 声明的变量会被提升…...
【llama_factory】qwen2_vl训练与批量推理
训练llama factory配置文件 文件:examples/train_lora/qwen2vl_lora_sft.yaml ### model model_name_or_path: qwen2_vl/model_72b trust_remote_code: true### method stage: sft do_train: true finetuning_type: lora lora_target: all### dataset dataset: ca…...
计算机视觉与深度学习:使用深度学习训练基于视觉的车辆检测器(MATLAB源码-Faster R-CNN)
在人工智能领域,计算机视觉是一个重要且充满活力的研究方向。它使计算机能够理解和分析图像和视频数据,从而做出有意义的决策。其中,目标检测是计算机视觉中的一项关键技术,它旨在识别并定位图像中的多个目标对象。车辆检测作为目标检测的一个重要应用,在自动驾驶、智能交…...
Python 扫描枪读取发票数据导入Excel
财务需要一个扫描枪扫描发票文件,并将主要信息录入Excel 的功能。 文件中sheet表的列名称,依次为:发票编号、发票编码、日期、金额、工号、扫描日期。 扫描的时候,Excel 文件需要关闭,否则会报错。 import openpyxl …...
SpringMVC复习笔记
文章目录 SpringMVC 概念和基本使用SpringMVC 简介SpringMVC 核心组件和调用流程SpringMVC 基本使用第一步:导入依赖第二步:Controller 层开发第三步:SpringMVC 配置类配置核心组件第四步:SpringMVC 环境搭建第五步:部…...
arcgis提取不规则栅格数据的矢量边界
效果 1、准备数据 栅格数据:dem或者dsm 2、栅格重分类 分成两类即可 3、新建线面图层 在目录下选择预先准备好的文件夹,点击右键,选择“新建”→“Shapefile”,新建一个Shapefile文件。 在弹出的“新建Shapefile”对话框内“名称”命名为“折线”,“要素类型”选…...
【机器学习】零售行业的智慧升级:机器学习驱动的精准营销与库存管理
我的个人主页 我的领域:人工智能篇,希望能帮助到大家!!!👍点赞 收藏❤ 在当今数字化浪潮汹涌澎湃的时代,零售行业正站在转型升级的十字路口。市场竞争的白热化使得企业必须另辟蹊径࿰…...
链路追踪SkyWalking
链路追踪 链路追踪作用链路追踪的关键概念链路追踪的工作原理常用链路追踪工具链路追踪的实现步骤链路追踪的典型场景 SkyWalkingSkyWalking 的主要功能SkyWalking 的架构安装 SkyWalking从 SkyWalking 的官方 GitHub 仓库 下载最新版本。配置后端存储SkyWalking使用࿰…...
linux下的线程
一、pthread 线程 线程可以说是轻量级的进程,一般是一个进程中的多个任务。 进程:系统中的最小资源分配单元 线程:系统中最小执行单元 二、线程的特征 1、共享资源 2、效率高30% 3.使用第三方库(头文件加pthread.h 编译时添加 -lpthre…...
《研发管理 APQP 软件系统》——汽车电子行业的应用收益分析
全星研发管理 APQP 软件系统在汽车电子行业的应用收益分析 在汽车电子行业,技术革新迅猛,市场竞争激烈。《全星研发管理 APQP 软件系统》的应用,为企业带来了革命性的变化,诸多收益使其成为行业发展的关键驱动力。 《全星研发管理…...
mysql、oracle、sqlserver的区别
一、保存数据的持久性: MySQL:是在数据库更新或者重启,则会丢失数据。 Oracle:把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复。 SqlServer:2…...
CV(10)--目标检测
前言 仅记录学习过程,有问题欢迎讨论 目标检测 object detection,就是在给定的图片中精确找到物体所在位置,并标注出物体的类别;输出的是分类类别label物体的外框(x, y, width, height)。 目标检测算法:…...
SQL LAST()
SQL中的LAST()函数是一个用于返回指定列中最后一个记录值的函数。然而,需要注意的是,这个函数并不是SQL标准的一部分,因此并不是所有数据库系统都支持它。具体来说,只有MS Access直接支持LAST()函数【0†source】。 在其他数据库…...
传统以太网问题与VLAN技术详解
传统以太网的问题 广播域:在网络中能接收同一广播信息的所有设备(计算机、交换机)等的集合 说明:在一个广播域内,当一个设备发送广播帧时,该域内的所有设备都能接收到这个广播帧。工作原理:在以…...
Java 面试题 - ArrayList 和 LinkedList 的区别,哪个集合是线程安全的?
Java 面试题 - ArrayList 和 LinkedList 的区别,哪个集合是线程安全的? 在 Java 开发中,ArrayList和LinkedList是两个常用的集合类,它们在数据结构和性能上有诸多不同,同时线程安全性也各有特点。深入理解这些差异&am…...
flutter 安卓端打包
在 Flutter 中打包 Android 应用程序是一个相对简单的过程。你可以使用 Flutter 的命令行工具来构建并打包你的 APK 或 AAB(Android App Bundle)。以下是打包 Flutter Android 应用的步骤: 1. 安装 Flutter 环境 确保你已经安装了 Flutter SDK,并且正确配置了 Android 开…...
前端开发:CSS背景属性
1.背景颜色 background-color: [ 指定颜色 ] background-color :blue; background-color : transparent //设置背景是透明的 2.背景图片 background-image : url ( ... ) 1. url 不要遗漏 . 2. url 可以是绝对路径 , 也可以是相对路径 3. url 上可以…...
【Python通过UDP协议传输视频数据】(界面识别)
提示:界面识别项目 前言 随着网络通信技术的发展,视频数据的实时传输在各种场景中得到了广泛应用。UDP(User Datagram Protocol)作为一种无连接的协议,凭借其低延迟、高效率的特性,在实时性要求较高的视频…...
centos 8 中安装Docker
注:本次样式安装使用的是centos8 操作系统。 1、镜像下载 具体的镜像下载地址各位可以去官网下载,选择适合你们的下载即可! 1、CentOS官方下载地址:https://vault.centos.org/ 2、阿里云开源镜像站下载:centos安装包…...
leetcode hot 100 -划分字母区间
给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。 返回一个表示每个字符串片段的长度的列表。 示例 1&am…...
CSS 元素的显示模式(块元素,行内元素,行内块元素)
一. 块元素(block) 又称:块级元素 特点: 1. 在页面中独占一行,不会与任何元素共用一行,是从上到下排列的。 2. 默认宽度:撑满父元素。 3. 默认高度:由内容撑开。 4. 可以通过 CSS 设…...