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

flink sink kafka的事务提交现象猜想

现象 

查看flink源码时 sink kafka有事务提交机制,查看源码发现是使用两阶段提交策略,而事务提交是checkpoint完成后才执行,那么如果checkpoint设置间隔时间比较长时,事务未提交之前,后端应该消费不到数据,而观察实际现象为写入kafka的消费数据可以立马消费。

测试用例

测试流程

  1. 编写任务1,设置较长的checkpoint时间,并且指定 CheckpointingMode.EXACTLY_ONCE,输出输出到kafka。
  2. 编写任务2消费任务的结果topic,打印控制台,验证结果。
  3. 根据现象查看源码,分析原因。

测试用例

测试任务1

 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);env.enableCheckpointing(1000*60l, CheckpointingMode.EXACTLY_ONCE);env.getCheckpointConfig().setCheckpointStorage("file:///flink/checkpoint");//        超时时间,checkpoint没在时间内完成则丢弃env.getCheckpointConfig().setCheckpointTimeout(50000L); //10秒env.getCheckpointConfig().setMaxConcurrentCheckpoints(2);env.getCheckpointConfig().setTolerableCheckpointFailureNumber(1);//最小间隔时间(前一次结束时间,与下一次开始时间间隔)env.getCheckpointConfig().setMinPauseBetweenCheckpoints(1000);
//        当 Flink 任务取消时,保留外部保存的 checkpoint 信息KafkaSource<String> source = KafkaSource.<String>builder().setBootstrapServers("127.0.0.1:9092").setTopics("test001").setGroupId("my-group")
//                .setStartingOffsets(OffsetsInitializer()).setStartingOffsets(OffsetsInitializer.committedOffsets()).setValueOnlyDeserializer(new SimpleStringSchema()).build();DataStreamSource<String> kafkaSource = env.fromSource(source, WatermarkStrategy.noWatermarks(), "Kafka Source");// 从文件读取数据
//        DataStream<SensorReading> dataStream = env.addSource( new SourceTest4.MySensorSource() );DataStream<String> map = kafkaSource.map(new MapFunction<String, String>() {@Overridepublic String map(String s) throws Exception {return s;}});Properties properties = new Properties();
// 根据上面的介绍自己计算这边的超时时间,满足条件即可properties.setProperty("transaction.timeout.ms","900000");
//        properties.setProperty("bootstrap.servers", "127.0.0.1:9092");KafkaSink<String> sink = KafkaSink.<String>builder().setBootstrapServers("192.168.65.128:9092").setRecordSerializer(KafkaRecordSerializationSchema.<String>builder().setTopic("test002").setValueSerializationSchema(new SimpleStringSchema()).build()).setKafkaProducerConfig(properties).setDeliverGuarantee(DeliveryGuarantee.EXACTLY_ONCE)
//                .setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE).setTransactionalIdPrefix("flink-xhaodream-").build();map.sinkTo(sink);// 打印输出env.execute();

测试任务2

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(1);env.enableCheckpointing(1000*150l, CheckpointingMode.EXACTLY_ONCE);env.getCheckpointConfig().setCheckpointStorage("file:///flink/checkpoint");
//        当 Flink 任务取消时,保留外部保存的 checkpoint 信息Properties properties1 = new Properties();
//        properties1.put("isolation.level","read_committed");KafkaSource<String> source = KafkaSource.<String>builder().setBootstrapServers("127.0.0.1:9092").setTopics("test002").setGroupId("my-group2").setProperties(properties1).setStartingOffsets(OffsetsInitializer.committedOffsets(OffsetResetStrategy.LATEST)).setValueOnlyDeserializer(new SimpleStringSchema()).build();DataStreamSource<String> kafkaSource = env.fromSource(source, WatermarkStrategy.noWatermarks(), "Kafka Source");kafkaSource.print(" test2接受数据");// 打印输出env.execute();

测试结果分析

测试结果:

任务1开启后,无论是否执行checkpoint,任务checkpoint都可以正常消费数据,与预期不符合。

原因排查

查看kafkaSink 的源码,找到跟与两阶段提交相关的代码,1.18源码中TwoPhaseCommittingSink有重构。kafkasink实现TwoPhaseCommittingSink接口实现,创建Commiter和Writer。

@PublicEvolving
public interface TwoPhaseCommittingSink<InputT, CommT> extends Sink<InputT> {PrecommittingSinkWriter<InputT, CommT> createWriter(Sink.InitContext var1) throws IOException;Committer<CommT> createCommitter() throws IOException;SimpleVersionedSerializer<CommT> getCommittableSerializer();@PublicEvolvingpublic interface PrecommittingSinkWriter<InputT, CommT> extends SinkWriter<InputT> {Collection<CommT> prepareCommit() throws IOException, InterruptedException;}
}--------------------------------------
public class KafkaSink<IN>implements StatefulSink<IN, KafkaWriterState>,TwoPhaseCommittingSink<IN, KafkaCommittable> {private final DeliveryGuarantee deliveryGuarantee;private final KafkaRecordSerializationSchema<IN> recordSerializer;private final Properties kafkaProducerConfig;private final String transactionalIdPrefix;KafkaSink(DeliveryGuarantee deliveryGuarantee,Properties kafkaProducerConfig,String transactionalIdPrefix,KafkaRecordSerializationSchema<IN> recordSerializer) {this.deliveryGuarantee = deliveryGuarantee;this.kafkaProducerConfig = kafkaProducerConfig;this.transactionalIdPrefix = transactionalIdPrefix;this.recordSerializer = recordSerializer;}/*** Create a {@link KafkaSinkBuilder} to construct a new {@link KafkaSink}.** @param <IN> type of incoming records* @return {@link KafkaSinkBuilder}*/public static <IN> KafkaSinkBuilder<IN> builder() {return new KafkaSinkBuilder<>();}
-- 创建Committer@Internal@Overridepublic Committer<KafkaCommittable> createCommitter() throws IOException {return new KafkaCommitter(kafkaProducerConfig);}@Internal@Overridepublic SimpleVersionedSerializer<KafkaCommittable> getCommittableSerializer() {return new KafkaCommittableSerializer();}
-- 创建writer@Internal@Overridepublic KafkaWriter<IN> createWriter(InitContext context) throws IOException {return new KafkaWriter<IN>(deliveryGuarantee,kafkaProducerConfig,transactionalIdPrefix,context,recordSerializer,context.asSerializationSchemaInitializationContext(),Collections.emptyList());}@Internal@Overridepublic KafkaWriter<IN> restoreWriter(InitContext context, Collection<KafkaWriterState> recoveredState) throws IOException {return new KafkaWriter<>(deliveryGuarantee,kafkaProducerConfig,transactionalIdPrefix,context,recordSerializer,context.asSerializationSchemaInitializationContext(),recoveredState);}@Internal@Overridepublic SimpleVersionedSerializer<KafkaWriterState> getWriterStateSerializer() {return new KafkaWriterStateSerializer();}@VisibleForTestingprotected Properties getKafkaProducerConfig() {return kafkaProducerConfig;}
}
KafkaWriter和KafkaCommitter源码,

在KafkaWriter中snapshotState方法中发现如果deliveryGuarantee == DeliveryGuarantee.EXACTLY_ONCE的开启事务的判断逻辑。

class KafkaWriter<IN>implements StatefulSink.StatefulSinkWriter<IN, KafkaWriterState>,TwoPhaseCommittingSink.PrecommittingSinkWriter<IN, KafkaCommittable> {
.... 省略代码  @Overridepublic Collection<KafkaCommittable> prepareCommit() {if (deliveryGuarantee != DeliveryGuarantee.EXACTLY_ONCE) {return Collections.emptyList();}// only return a KafkaCommittable if the current transaction has been written some dataif (currentProducer.hasRecordsInTransaction()) {final List<KafkaCommittable> committables =Collections.singletonList(KafkaCommittable.of(currentProducer, producerPool::add));LOG.debug("Committing {} committables.", committables);return committables;}// otherwise, we commit the empty transaction as is (no-op) and just recycle the producercurrentProducer.commitTransaction();producerPool.add(currentProducer);return Collections.emptyList();}@Overridepublic List<KafkaWriterState> snapshotState(long checkpointId) throws IOException {
-- 开启事务判断        
if (deliveryGuarantee == DeliveryGuarantee.EXACTLY_ONCE) {currentProducer = getTransactionalProducer(checkpointId + 1);currentProducer.beginTransaction();}return Collections.singletonList(kafkaWriterState);}
。。。。。
}

 查看 KafkaCommitter的commit()方法发现producer.commitTransaction();操作

/*** Committer implementation for {@link KafkaSink}** <p>The committer is responsible to finalize the Kafka transactions by committing them.*/
class KafkaCommitter implements Committer<KafkaCommittable>, Closeable {private static final Logger LOG = LoggerFactory.getLogger(KafkaCommitter.class);public static final String UNKNOWN_PRODUCER_ID_ERROR_MESSAGE ="because of a bug in the Kafka broker (KAFKA-9310). Please upgrade to Kafka 2.5+. If you are running with concurrent checkpoints, you also may want to try without them.\n"+ "To avoid data loss, the application will restart.";private final Properties kafkaProducerConfig;@Nullable private FlinkKafkaInternalProducer<?, ?> recoveryProducer;KafkaCommitter(Properties kafkaProducerConfig) {this.kafkaProducerConfig = kafkaProducerConfig;}@Overridepublic void commit(Collection<CommitRequest<KafkaCommittable>> requests)throws IOException, InterruptedException {for (CommitRequest<KafkaCommittable> request : requests) {final KafkaCommittable committable = request.getCommittable();final String transactionalId = committable.getTransactionalId();LOG.debug("Committing Kafka transaction {}", transactionalId);Optional<Recyclable<? extends FlinkKafkaInternalProducer<?, ?>>> recyclable =committable.getProducer();FlinkKafkaInternalProducer<?, ?> producer;try {producer =recyclable.<FlinkKafkaInternalProducer<?, ?>>map(Recyclable::getObject).orElseGet(() -> getRecoveryProducer(committable));--- 事务提交producer.commitTransaction();producer.flush();recyclable.ifPresent(Recyclable::close);} catch (RetriableException e) {LOG.warn("Encountered retriable exception while committing {}.", transactionalId, e);request.retryLater();} catch (ProducerFencedException e) {......}}}
。。。。
}
分析结果

发现除了设置checkpoint还需要kafkasink单独设置.才会实现输出端的开启事务,因此在任务1中添加设置setDeliverGuarantee(DeliveryGuarantee.EXACTLY_ONCE)

 KafkaSink<String> sink = KafkaSink.<String>builder().setBootstrapServers("192.168.65.128:9092").setRecordSerializer(KafkaRecordSerializationSchema.<String>builder().setTopic("test002").setValueSerializationSchema(new SimpleStringSchema()).build()).setKafkaProducerConfig(properties).setDeliverGuarantee(DeliveryGuarantee.EXACTLY_ONCE)
//                .setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE).setTransactionalIdPrefix("flink-xhaodream-").build();

再次验证任务任务2依然可以正常消费。这是有一点头大,不明白为什么?想到既然开启事务肯定有事务的隔离级别,查询了kafka的事务隔离级别,有两种,分别是读已提交和读未提交,默认消费事务是读未提交。

​
kafka的事务隔离级别:
读已提交(Read committed):此隔离级别保证消费者只能读取已经提交的消息。这意味着事务中的消息在提交之前对消费者是不可见的。使用此隔离级别可以避免消费者读取到未提交的事务消息,确保消费者只读取到已经持久化的消息。读未提交(Read Uncommitted):此隔离级别允许消费者读取未提交的消息。这意味着事务中的消息在提交之前就对消费者可见。使用此隔离级别可以实现更低的延迟,但可能会导致消费者读取到未提交的事务消息。​

在任务2中添加isolation.level="read_committed",设定读取消费事务级别为读已提交,再次测试,发现任务1执行完checkpoint前任务2消费不到数据。而命令行可以及时消费任务1的输出topic可可以消费到数据。结果与预期相同。

 Properties properties1 = new Properties();properties1.put("isolation.level","read_committed");KafkaSource<String> source = KafkaSource.<String>builder().setBootstrapServers("127.0.0.1:9092").setTopics("test002").setGroupId("my-group2").setProperties(properties1)

注意事项

Kafka | Apache Flink

FlinkKafkaProducer 已被弃用并将在 Flink 1.15 中移除,请改用 KafkaSink

官网文档信息

Kafka | Apache Flink

Kafka Consumer 提交 Offset 的行为配置 #

Flink Kafka Consumer 允许有配置如何将 offset 提交回 Kafka broker 的行为。请注意:Flink Kafka Consumer 不依赖于提交的 offset 来实现容错保证。提交的 offset 只是一种方法,用于公开 consumer 的进度以便进行监控。

配置 offset 提交行为的方法是否相同,取决于是否为 job 启用了 checkpointing。

  • 禁用 Checkpointing: 如果禁用了 checkpointing,则 Flink Kafka Consumer 依赖于内部使用的 Kafka client 自动定期 offset 提交功能。 因此,要禁用或启用 offset 的提交,只需将 enable.auto.commit 或者 auto.commit.interval.ms 的Key 值设置为提供的 Properties 配置中的适当值。

  • 启用 Checkpointing: 如果启用了 checkpointing,那么当 checkpointing 完成时,Flink Kafka Consumer 将提交的 offset 存储在 checkpoint 状态中。 这确保 Kafka broker 中提交的 offset 与 checkpoint 状态中的 offset 一致。 用户可以通过调用 consumer 上的 setCommitOffsetsOnCheckpoints(boolean) 方法来禁用或启用 offset 的提交(默认情况下,这个值是 true )。 注意,在这个场景中,Properties 中的自动定期 offset 提交设置会被完全忽略。

kafkasink支持语义保证

kafkaSink 总共支持三种不同的语义保证(DeliveryGuarantee)。对于 DeliveryGuarantee.AT_LEAST_ONCE 和 DeliveryGuarantee.EXACTLY_ONCE,Flink checkpoint 必须启用。默认情况下 KafkaSink 使用 DeliveryGuarantee.NONE。 以下是对不同语义保证的解释:

  • DeliveryGuarantee.NONE 不提供任何保证:消息有可能会因 Kafka broker 的原因发生丢失或因 Flink 的故障发生重复。
  • DeliveryGuarantee.AT_LEAST_ONCE: sink 在 checkpoint 时会等待 Kafka 缓冲区中的数据全部被 Kafka producer 确认。消息不会因 Kafka broker 端发生的事件而丢失,但可能会在 Flink 重启时重复,因为 Flink 会重新处理旧数据。
  • DeliveryGuarantee.EXACTLY_ONCE: 该模式下,Kafka sink 会将所有数据通过在 checkpoint 时提交的事务写入。因此,如果 consumer 只读取已提交的数据(参见 Kafka consumer 配置 isolation.level),在 Flink 发生重启时不会发生数据重复。然而这会使数据在 checkpoint 完成时才会可见,因此请按需调整 checkpoint 的间隔。请确认事务 ID 的前缀(transactionIdPrefix)对不同的应用是唯一的,以保证不同作业的事务 不会互相影响!此外,强烈建议将 Kafka 的事务超时时间调整至远大于 checkpoint 最大间隔 + 最大重启时间,否则 Kafka 对未提交事务的过期处理会导致数据丢失。

推荐查看1.14版本和1.18版本结合起来看,在一些细节处理上有差异。

Kafka | Apache Flink

其他源码简介

如果查看1.18版本源码不太好理解两阶段提交,可以查看1.14.5的源码,发现FlinkKafkaProducer被标记废除请改用 KafkaSink,并将在 Flink 1.15 中移除, 在1.14.5中TwoPhaseCommitSinkFunction为抽象类,有明确定开启事务、预提交和提交的抽象方法,比较好理解。

 查看1.14.5版本的KafkaSink 的依赖,发现没有直接使用TwoPhaseCommitSinkFunction,但是查看源码可以看到使用了commiter和kafkawriter对象

public class KafkaSink<IN> implements Sink<IN, KafkaCommittable, KafkaWriterState, Void> {   public static <IN> KafkaSinkBuilder<IN> builder() {return new KafkaSinkBuilder<>();}
-- KafkaWriter 中会判断是否需要开启事务@Overridepublic SinkWriter<IN, KafkaCommittable, KafkaWriterState> createWriter(InitContext context, List<KafkaWriterState> states) throws IOException {final Supplier<MetricGroup> metricGroupSupplier =() -> context.metricGroup().addGroup("user");return new KafkaWriter<>(deliveryGuarantee,kafkaProducerConfig,transactionalIdPrefix,context,recordSerializer,new InitContextInitializationContextAdapter(context.getUserCodeClassLoader(), metricGroupSupplier),states);}-- 事务提交在kafkaCommitter@Overridepublic Optional<Committer<KafkaCommittable>> createCommitter() throws IOException {return Optional.of(new KafkaCommitter(kafkaProducerConfig));}@Overridepublic Optional<GlobalCommitter<KafkaCommittable, Void>> createGlobalCommitter()throws IOException {return Optional.empty();}...
}

KafkaWriter源码

@Overridepublic List<KafkaCommittable> prepareCommit(boolean flush) {if (deliveryGuarantee != DeliveryGuarantee.NONE || flush) {currentProducer.flush();}if (deliveryGuarantee == DeliveryGuarantee.EXACTLY_ONCE) {final List<KafkaCommittable> committables =Collections.singletonList(KafkaCommittable.of(currentProducer, producerPool::add));LOG.debug("Committing {} committables, final commit={}.", committables, flush);return committables;}return Collections.emptyList();}
-- 快照状态开启事务@Overridepublic List<KafkaWriterState> snapshotState(long checkpointId) throws IOException {if (deliveryGuarantee == DeliveryGuarantee.EXACTLY_ONCE) {currentProducer = getTransactionalProducer(checkpointId + 1);currentProducer.beginTransaction();}return ImmutableList.of(kafkaWriterState);}

1.14.5 版本TwoPhaseCommitSinkFunction是一个抽象类 在1.18 中是接口

/*** Flink Sink to produce data into a Kafka topic. By default producer will use {@link* FlinkKafkaProducer.Semantic#AT_LEAST_ONCE} semantic. Before using {@link* FlinkKafkaProducer.Semantic#EXACTLY_ONCE} please refer to Flink's Kafka connector documentation.** @deprecated Please use {@link org.apache.flink.connector.kafka.sink.KafkaSink}.*/
@Deprecated
@PublicEvolving
public class FlinkKafkaProducer<IN>extends TwoPhaseCommitSinkFunction<IN,FlinkKafkaProducer.KafkaTransactionState,FlinkKafkaProducer.KafkaTransactionContext> {。。。}
-- 1.14 版本TwoPhaseCommitSinkFunction 为抽象类@PublicEvolving
public abstract class TwoPhaseCommitSinkFunction<IN, TXN, CONTEXT> extends RichSinkFunction<IN>implements CheckpointedFunction, CheckpointListener { }-- 1.18 版本
@PublicEvolving
public interface TwoPhaseCommittingSink<InputT, CommT> extends Sink<InputT> {PrecommittingSinkWriter<InputT, CommT> createWriter(Sink.InitContext var1) throws IOException;Committer<CommT> createCommitter() throws IOException;SimpleVersionedSerializer<CommT> getCommittableSerializer();@PublicEvolvingpublic interface PrecommittingSinkWriter<InputT, CommT> extends SinkWriter<InputT> {Collection<CommT> prepareCommit() throws IOException, InterruptedException;}
}

FlinkKafkaProducer继承TwoPhaseCommitSinkFunction,会重写其中的方法,查看重写开启事务的方法
  -- FlinkKafkaProducer 中重写beginTransaction 方法@Overrideprotected FlinkKafkaProducer.KafkaTransactionState beginTransaction()throws FlinkKafkaException {switch (semantic) {case EXACTLY_ONCE:FlinkKafkaInternalProducer<byte[], byte[]> producer = createTransactionalProducer();
-- 开启kafka的procder的事务producer.beginTransaction();return new FlinkKafkaProducer.KafkaTransactionState(producer.getTransactionalId(), producer);case AT_LEAST_ONCE:case NONE:// Do not create new producer on each beginTransaction() if it is not necessaryfinal FlinkKafkaProducer.KafkaTransactionState currentTransaction =currentTransaction();if (currentTransaction != null && currentTransaction.producer != null) {return new FlinkKafkaProducer.KafkaTransactionState(currentTransaction.producer);}return new FlinkKafkaProducer.KafkaTransactionState(initNonTransactionalProducer(true));default:throw new UnsupportedOperationException("Not implemented semantic");}}

只有当FlinkKafkaProducer.Semantic 为EXACTLY_ONCE时才会开启事务,查看其构造方法

 public FlinkKafkaProducer(String topicId,SerializationSchema<IN> serializationSchema,Properties producerConfig,@Nullable FlinkKafkaPartitioner<IN> customPartitioner,FlinkKafkaProducer.Semantic semantic,int kafkaProducersPoolSize) {this(topicId,null,null,new KafkaSerializationSchemaWrapper<>(topicId, customPartitioner, false, serializationSchema),producerConfig,semantic,kafkaProducersPoolSize);}

相关文章:

flink sink kafka的事务提交现象猜想

现象 查看flink源码时 sink kafka有事务提交机制&#xff0c;查看源码发现是使用两阶段提交策略&#xff0c;而事务提交是checkpoint完成后才执行&#xff0c;那么如果checkpoint设置间隔时间比较长时&#xff0c;事务未提交之前&#xff0c;后端应该消费不到数据&#xff0c…...

网络原理03

回顾 应用层&#xff1a;应用程序&#xff0c;数据具体如何使用 传输层&#xff1a;关注起点和终点 网络层&#xff1a;关注路径规划 数据链路层&#xff1a;关注相邻节点的转发 物理层&#xff1a;硬件设备 应用层 应用程序 在应用层&#xff0c;很多时候&#xff0c;…...

每天40分玩转Django:简介和环境搭建

Django简介和环境搭建 一、课程概述 学习项目具体内容预计用时Django概念Django框架介绍、MVC/MTV模式、Django特点60分钟环境搭建Python安装、pip配置、Django安装、IDE选择45分钟创建项目项目结构、基本配置、运行测试75分钟实战练习创建个人博客项目框架60分钟 二、Djang…...

【蓝桥杯最新板】蓝桥杯嵌入式液晶上实现电子时钟

这几年蓝桥杯比赛比较适合学生技能学习&#xff0c;考虑板子功能&#xff0c;提出完成的任务。 要求在液晶完成如下图效果&#xff1a; 主要是实现液晶显示时钟和数字时钟&#xff0c;具体样式可以依据实际情况微调。 实现过程&#xff1a; 1.需要画圆&#xff08;外圆、内圆…...

【机器学习】基础知识:拟合度(Goodness of Fit)

拟合度概念及意义 拟合度&#xff08;Goodness of Fit&#xff09;是衡量统计模型对数据解释能力的指标&#xff0c;用于评价模型对观测数据的拟合效果。在回归分析、分类模型或其他预测模型中&#xff0c;拟合度是模型性能的重要衡量标准。 1. 拟合度的作用 拟合度的主要作用…...

使用Jackson库在Java应用程序中将Map对象转换为JSON数组字符串,以及反向操作

在现代Java应用程序中&#xff0c;特别是使用RESTful Web服务时&#xff0c;经常需要将Java对象转换为JSON格式&#xff0c;反之亦然。 当表示如用户管理系统中的用户列表这样的数据结构时&#xff0c;将Map转换为JSON数组字符串变得非常有用。在这个指南中&#xff0c;我们将…...

深入解析强化学习中的 Generalized Advantage Estimation (GAE)

中文版 深入解析强化学习中的 Generalized Advantage Estimation (GAE) 1. 什么是 Generalized Advantage Estimation (GAE)? 在强化学习中&#xff0c;计算策略梯度的关键在于 优势函数&#xff08;Advantage Function&#xff09; 的设计。优势函数 ( A ( s , a ) A(s, a…...

离开wordpress

wordpress确实挺好用的 插件丰富 主题众多 收费的插件也很多 国内的做主题的也挺好 但是服务器跑起来各种麻烦伤脑筋 需要花在维护的时间太多了 如果你的网站持续盈利 你就会更担心访问质量访问速度 而乱七八糟的爬虫黑客 让你的服务器不堪重负 突然有一天看到了静态站…...

Python的3D可视化库【vedo】1-4 (visual模块) 体素可视化、光照控制、Actor2D对象

文章目录 6. VolumeVisual6.1 关于体素6.2 显示效果6.2.1 遮蔽6.2.2 木纹或磨砂效果 6.3 颜色和透明度6.3.1 透明度衰减单位6.3.2 划分透明度标量梯度6.3.3 设置颜色或渐变6.3.4 标量的计算模式6.3.5 标量的插值方式 6.4 过滤6.4.1 按单元格id隐藏单元格6.4.2 按二进制矩阵设置…...

使用html和JavaScript实现一个简易的物业管理系统

码实现了一个简易的物业管理系统&#xff0c;主要使用了以下技术和功能&#xff1a; 1.主要技术 使用的技术&#xff1a; HTML: 用于构建网页的基本结构。包括表单、表格、按钮等元素。 CSS: 用于美化网页的外观和布局。设置字体、颜色、边距、对齐方式等样式。 JavaScript…...

什么是纯虚函数?什么是抽象类?纯虚函数和抽象类在面向对象编程中的意义是什么?

纯虚函数 纯虚函数是一个在基类中声明但不实现的虚函数。它的声明方式是在函数声明的末尾添加 0。这意味着这个函数没有提供具体的实现&#xff0c;任何继承这个基类的派生类都必须提供这个函数的实现&#xff0c;否则它们也会变成抽象类&#xff0c;无法实例化。 示例&#…...

#Ts篇: Record<string, number> 是 TypeScript 中的一种类型定义,它表示一个键值对集合

Record<string, number> 是 TypeScript 中的一种类型定义&#xff0c;它表示一个键值对集合&#xff0c;其中键的类型是 string&#xff0c;而值的类型是 number。具体来说&#xff0c;Record<K, T> 是 TypeScript 的一个内置高级类型&#xff0c;用于根据传入的键…...

Exp 智能协同管理系统前端首页框架开发

一、 需求分析 本案例的主要目标是开发一个智能学习辅助系统的前端界面&#xff0c;涵盖以下功能模块&#xff1a; 首页&#xff1a;显示系统的总体概览和关键功能介绍。 班级学员管理&#xff1a;实现班级管理和学员管理。 系统信息管理&#xff1a;管理部门和员工信息。 …...

C# 备份文件夹

C# 备份目标文件夹 方法1&#xff1a;通过 递归 或者 迭代 结合 C# 方法 参数说明&#xff1a; sourceFolder&#xff1a;源文件夹路径destinationFolder&#xff1a;目标路径excludeNames&#xff1a;源文件夹中不需备份的文件或文件夹路径哈希表errorLog&#xff1a;输出错…...

互联网信息泄露与安全扫描工具汇总

文章目录 1. 代码托管平台渠道泄露2. 网盘渠道泄露3. 文章渠道泄露4. 文档渠道泄露5. 暗网渠道泄露6. 互联网IP信誉度排查7. 网站挂马暗链扫描8. 互联网IP端口扫描9. 互联网资产漏洞扫描 1. 代码托管平台渠道泄露 https://github.com/ https://gitee.com/ https://gitcode.co…...

主导极点,传递函数零极点与时域模态

运动模态 控制系统的数学建模&#xff0c;可以采用微分方程或传递函数&#xff0c;两者具有相同的特征方程。在数学上&#xff0c;微分方程的解由特解和通解组成&#xff0c;具体求解过程可以参考&#xff1a;微分方程求解的三种解析方法。 如果 n n n阶微分方程&#xff0c;具…...

永恒之蓝漏洞利用什么端口

永恒之蓝&#xff08;EternalBlue&#xff09;是一个著名的漏洞&#xff0c;影响了 Windows 操作系统的 SMBv1 服务。它的漏洞编号是 CVE-2017-0144&#xff0c;该漏洞被用于 WannaCry 等勒索病毒的传播。 永恒之蓝漏洞利用的端口 永恒之蓝漏洞利用的是 SMB&#xff08;Server…...

网络安全与防范

1.重要性 随着互联网的发达&#xff0c;各种WEB应用也变得越来越复杂&#xff0c;满足了用户的各种需求&#xff0c;但是随之而来的就是各种网络安全的问题。了解常见的前端攻击形式和保护我们的网站不受攻击是我们每个优秀fronter必备的技能。 2.分类 XSS攻击CSRF攻击网络劫…...

Navicat 17 功能简介 | SQL 开发

Navicat 17 功能简介 | SQL 开发 随着 17 版本的发布&#xff0c;Navicat 也带来了众多的新特性&#xff0c;包括兼容更多数据库、全新的模型设计、可视化智能 BI、智能数据分析、可视化查询解释、高质量数据字典、增强用户体验、扩展 MongoDB 功能、轻松固定查询结果、便捷URI…...

嵌入式系统中的并行编程模型:汇总解析与应用

概述&#xff1a;随着嵌入式系统处理能力的不断提升&#xff0c;并行编程在其中的应用愈发广泛。本文深入探讨了多种专门为嵌入式设计的并行编程模型&#xff0c;包括任务队列模型、消息传递模型、数据并行模型、异构多核并行模型、实时任务调度模型以及函数式并行模型。详细阐…...

VulkanSamples编译记录

按照BUILD.md说明&#xff0c;先安装依赖项 sudo apt-get install git build-essential libx11-xcb-dev \libxkbcommon-dev libwayland-dev libxrandr-dev 然后创建一个新文件夹build&#xff0c;在该目录下更新依赖项 cd VulkanSamples mkdir build cd build python ../scr…...

使用FabricJS对大图像应用滤镜(巨坑)

背景:我司在canvas的渲染模板的宽高都大于2048px 都几乎接近4000px&#xff0c;就导致使用FabricJS的滤镜功能图片显示异常 新知识:滤镜是对图片纹理的处理 FabricJS所能支持的最大图片纹理是2048的 一但图片超出2048的纹理尺寸 当应用滤镜时&#xff0c;图像会被剪切或者是缩…...

网页502 Bad Gateway nginx1.20.1报错与解决方法

目录 网页报错的原理 查到的502 Bad Gateway报错的原因 出现的问题和尝试解决 问题 解决 网页报错的原理 网页显示502 Bad Gateway 报错原理是用户访问服务器时&#xff0c;nginx代理服务器接收用户信息&#xff0c;但无法反馈给服务器&#xff0c;而出现的报错。 查到…...

Spring基础分析02-BeanFactory与ApplicationContext

大家好&#xff0c;今天和大家一起学习整理一下Spring 的BeanFactory和ApplicationContext内容和区别~ BeanFactory和ApplicationContext是Spring IoC容器的核心组件&#xff0c;负责管理应用程序中的Bean生命周期和配置。我们深入分析一下这两个接口的区别、使用场景及其提供…...

Rerender A Video 技术浅析(五):对象移除与自动配色

Rerender A Video 是一种基于深度学习和计算机视觉技术的视频处理工具&#xff0c;旨在通过智能算法对视频进行重新渲染和优化。 一、对象移除模块 1. 目标检测 1.1 概述 目标检测是对象移除的第一步&#xff0c;旨在识别视频中需要移除的对象并生成相应的掩码&#xff08;m…...

Java项目实战II基于微信小程序的小区租拼车管理信息系统 (开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 随着城市化进程的加速&#xff0c;小区居民对于出行方…...

【数字花园】数字花园(个人网站、博客)搭建经历汇总教程

目录 写在最最前面第一章&#xff1a;netlify免费搭建数字花园相关教程使用的平台步骤信息管理 第二章&#xff1a;本地部署数字花园数字花园网站本地手动部署方案1. 获取网站源码2.2 安装 Node.js 3. 项目部署3.1 安装项目依赖3.2 构建项目3.3 启动http服务器 4. 本地预览5. 在…...

WebRTC服务质量(03)- RTCP协议

一、前言&#xff1a; RTCP&#xff08;RTP Control Protocol&#xff09;是一种控制协议&#xff0c;与RTP&#xff08;Real-time Transport Protocol&#xff09;一起用于实时通信中的控制和反馈。RTCP负责监控和调节实时媒体流。通过不断交换RTCP信息&#xff0c;WebRTC应用…...

STM32F103单片机HAL库串口通信卡死问题解决方法

在上篇文章 STM32F103单片机使用STM32CubeMX创建IAR串口工程 中分享了使用cubeMX直接生成串口代码的方法&#xff0c;在测试的过程中无意间发现&#xff0c;串口会出现卡死的问题。 当串口一次性发送十几个数据的时候&#xff0c;串口感觉像卡死了一样&#xff0c;不再接收数据…...

Scala正则表达式

一、定义&#xff1a;正则表达式是一种用于匹配、查找和替换文本中特定模式的字符串。 使用方式&#xff1a;①定义一个正则 正则表达式应用场景&#xff1a;查找、验证、替换。 Ⅰ、查找 在目标字符串中&#xff0c;找到符合正则表达式规则要求的 子串。 方括号&#xff…...

响应式网站排名/网络网站推广选择乐云seo

1、C工程的组成c程序是由一个或者多个.c文件和.h文件组成的。其中 .c文件是c源代码文件&#xff0c;是程序具体实现的部分。.h文件时C的头文件&#xff0c;用来声明.c文件中函数的。也可以申明自定义的数据。如下图&#xff0c;我定义了一个宏&#xff1a;#define kAD_MAX_DIM …...

外贸网站开发莆田/陕西网站建设制作

每天一习题&#xff0c;提升Python不是问题&#xff01;&#xff01;有更简洁的写法请评论告知我&#xff01; https://www.cnblogs.com/poloyy/category/1676599.html 题目 打印99乘法表 解题思路 外层循环&#xff0c;获取被乘数内层循环&#xff0c;获取乘数 答案 for i in …...

龙岗区最新通告/提高seo关键词排名

goldengate for sqlserver 日志暴涨的解决办法 gg for sqlserver 2008 R2 开启后&#xff0c;sqlserver的日志会出现暴涨的情况&#xff0c;解决办法如下&#xff1a; 1.先确认是否数据库设置问题导致 如&#xff1a; 1)查看ggerror中&#xff0c;是否有报错&#xff01; 2)…...

廊坊网站设计公司/网站开发需要的技术

打开项目的jar包&#xff0c;发现这个类是空的&#xff08;如下图&#xff09; 于是在网上找了相关的资料&#xff0c;发现原本这个类是包含在xalan.jar中的&#xff0c;但是xalan-j2.7.0版的发布包中&#xff0c;将serializer包中的类单独打包成serializer.jar&#xff0c;不再…...

Axure只是做网站吗/2023年免费进入b站

转自&#xff1a;http://blog.csdn.net/yikai2009/article/details/8653697 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 目录(?)[-] 阻塞阻塞操作非阻塞操作阻塞方式-read- 实现阻塞方式-write- 实现非阻塞方式的读写操作实例 --- 读阻塞的实…...

如何租用服务器做网站/长安seo排名优化培训

MPI简介在程序中&#xff0c;不同的进程需要相互的数据交换&#xff0c;特别是在科学计算中&#xff0c;需要大规模的计算与数据交换&#xff0c;集群可以很好解决单节点计算力不足的问题&#xff0c;但在集群中大规模的数据交换是很耗费时间的&#xff0c;因此需要一种在多节点…...