赞
踩
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
KafkaSink是Apache Flink中用于将流式数据写入Apache Kafka的关键组件。其工作原理涉及几个主要步骤,同时我将介绍一些源码片段以解释其内部实现。
用户需要配置Kafka连接属性,包括Kafka服务器地址、序列化器等。在Flink中,这通常通过创建Properties对象来完成。
// 创建KafksSink配置
Properties properties = new Properties();
properties.setProperty(ProducerConfig.ACKS_CONFIG, "1");
properties.setProperty(ProducerConfig.LINGER_MS_CONFIG, "0");
properties.setProperty(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, "10000");
KafkaRecordSerializationSchema
是 Apache Flink 中用于将数据流转换为 Kafka 记录(record)的序列化模式(Serialization Schema)。它允许将 Flink 数据流中的元素转换为 Kafka 生产者记录,并定义了如何序列化元素的逻辑。
在 Flink 中,当你想要将数据发送到 Kafka 主题,需要一个序列化模式来将 Flink 数据流中的元素序列化为 Kafka 记录。而 KafkaRecordSerializationSchema
就是为此目的而设计的。
// 序列化模式
KafkaRecordSerializationSchema<String> recordSerializer = KafkaRecordSerializationSchema.builder()
//设置对哪个主题进行序列化
.setTopic("topic_a")
//设置数据值序列化方式
.setValueSerializationSchema(new SimpleStringSchema())
//设置数据key序列化方式
.setKeySerializationSchema(new SimpleStringSchema())
.build();
使用Flink提供的KafkaSink
类创建一个Kafka生产者实例。以下是简化的源码片段,展示了如何创建实例:
注意:如果传递保证选择Exactly Once (精确一次),需要设置 客户端的超时时间 ,否则会报错
Caused by: org.apache.kafka.common.KafkaException: Unexpected error in InitProducerIdResponse; The transaction timeout is larger than the maximum value allowed by the broker (as configured by transaction.max.timeout.ms),需要设置 transaction.timeout.ms 小于15分钟,后续会专门出一篇关于这个传递保证的博客讲述。
// 创建KafkaSink算子 KafkaSink<String> kafkaSink = KafkaSink.<String>builder() //设置kafka各种参数 .setKafkaProducerConfig(properties) //设置序列化模式 .setRecordSerializer(recordSerializer) //设置传递保证 //At Most Once (至多一次): 系统保证消息要么被成功传递一次,要么根本不被传递。这种保证意味着消息可能会丢失,但不会被传递多 //At Least Once (至少一次): 系统保证消息至少会被传递一次,但可能会导致消息的重复传递。这种保证确保了消息的不丢失,但应用 //Exactly Once (精确一次): 系统保证消息会被确切地传递一次,而没有任何重复。这是最高级别的传递保证,确保消息不会丢失且不会 .setDeliverGuarantee(DeliveryGuarantee.AT_LEAST_ONCE) //设置集群地址 .setBootstrapServers("127.0.0.1:9092") //设置事务前缀 .setTransactionalIdPrefix("flink_") .build();
创建数据源,每隔1000ms下发一笔数据
// 生成一个数据流 SourceFunction<String> sourceFunction = new SourceFunction<String>() { @Override public void run(SourceContext<String> sourceContext) throws Exception { while (true) { String id = UUID.randomUUID().toString(); sourceContext.collect( id); logger.info("正在下发数据:{}",id); Thread.sleep(1000); } } @Override public void cancel() { } // 创建数据源 DataStreamSource<String> dataStreamSource = env.addSource(sourceFunction).setParallelism(1);
在Flink应用程序中,通过addSink()
方法将要写入Kafka主题数据流添加到KafkaSink,以下是一个简化的示例:
// 数据流数据通过KafkaSink算子写入kafka
dataStreamSource.sinkTo(kafkaSink).setParallelism(1);
// 执行任务
env.execute("KafkaSinkStreamJobDemo");
KafkaSink会将接收到的数据流分区为若干个并行的数据流,每个并行数据流由一个Kafka生产者实例负责向Kafka主题写入数据。这样可以提高写入的吞吐量和并行度。
以下是源码中的一部分,展示了KafkaSink是如何将数据发送到Kafka的:
@Override
public void invoke(IN value, Context context) throws Exception {
// 将数据发送到Kafka主题
producer.send(new ProducerRecord<>(topic, value.toString()));
}
KafkaSink的源码相对复杂,涉及到与Kafka的交互、并行处理、容错等方面的实现。
总的来说,KafkaSink通过整合Flink和Kafka的功能,提供了一种高效、可靠的方式将流式数据写入Kafka主题,适用于各种实时数据处理场景。
需要根据具体的安全需求和环境配置 Kafka 的安全性参数。建议查阅最新版本的 Kafka 文档以获取详细的安全配置指南:https://kafka.apache.org/documentation/#producerconfigs
在 Apache Flink 中,ProducerConfig
是用于配置 Kafka 生产者的类,它是 Kafka 客户端库中的一部分。下面是一些常见的配置选项及其解释:
bootstrap.servers
集群的地址列表,用于初始化连接。生产者会从这些服务器中选择一个 broker 进行连接。
public static final String BOOTSTRAP_SERVERS_CONFIG = "bootstrap.servers";
metadata.max.age.ms
元数据的最大缓存时间。在此时间内,生产者将重复使用已经获取的元数据,而不会向服务器发送新的元数据请求
public static final String METADATA_MAX_AGE_CONFIG = "metadata.max.age.ms";
batch.size
控制批量发送到 Kafka 的消息大小。当消息积累到一定大小时,生产者会将它们一起发送到 Kafka 以提高效率
public static final String BATCH_SIZE_CONFIG = "batch.size";
acks
消息确认机制,控制生产者收到确认的方式。可以是“all”(所有副本都确认),“1”(至少一个副本确认)或“0”(不需要确认)
public static final String ACKS_CONFIG = "acks";
linger.ms
生产者在发送批量消息前等待的时间,以使更多的消息聚合成一个批次。默认是0,表示立即发送
public static final String LINGER_MS_CONFIG = "linger.ms";
request.timeout.ms
发送请求到 Kafka 服务器的超时时间
public static final String REQUEST_TIMEOUT_MS_CONFIG = "request.timeout.ms";
delivery.timeout.ms
这个参数在 Kafka 生产者的配置中是存在的,它表示生产者在发送消息后等待生产者确认的最大时间。如果在这段时间内没有收到确认,生产者将重试发送消息或者抛出异常,具体取决于 retries 参数的配置
public static final String DELIVERY_TIMEOUT_MS_CONFIG = "delivery.timeout.ms";
client.id
用于区分不同生产者实例的客户端 ID
public static final String CLIENT_ID_CONFIG = "client.id";
send.buffer.bytes
Kafka 消费者用于网络 socket 发送数据的缓冲区大小
public static final String SEND_BUFFER_CONFIG = "send.buffer.bytes";
receive.buffer.bytes
Kafka 消费者用于网络 socket 接收数据的缓冲区大小
public static final String RECEIVE_BUFFER_CONFIG = "receive.buffer.bytes";
max.request.size
单个请求发送的最大字节数
public static final String MAX_REQUEST_SIZE_CONFIG = "max.request.size";
reconnect.backoff.ms
用于控制在与 Kafka 服务器连接断开后重新连接的时间间隔。具体来说,它定义了在发起重新连接尝试之间等待的时间量,以毫秒为单位。如果连接失败,生产者将在此时间间隔之后尝试重新连接到 Kafka 服务器
public static final String RECONNECT_BACKOFF_MS_CONFIG = "reconnect.backoff.ms";
reconnect.backoff.max.ms
用于控制重新连接的最大退避时间。具体来说,它定义了在发起重新连接尝试之间等待的最长时间量,以毫秒为单位。如果连接失败,生产者将在此时间间隔之后尝试重新连接到 Kafka 服务器
public static final String RECONNECT_BACKOFF_MAX_MS_CONFIG = "reconnect.backoff.max.ms";
max.block.ms
当 Kafka 队列已满时,生产者将阻塞的最长时间(毫秒),超时后会抛出异常
public static final String MAX_BLOCK_MS_CONFIG = "max.block.ms";
buffer.memory
生产者用于缓冲等待发送到服务器的消息的内存大小。默认是33554432字节(32MB)
public static final String BUFFER_MEMORY_CONFIG = "buffer.memory";
retries
生产者发送失败后的重试次数。默认是0,表示不重试
public static final String RETRIES_CONFIG = "retries";
key.serializer
用于序列化消息键的序列化器类。通常是指实现了Serializer接口的类的全限定名
public static final String KEY_SERIALIZER_CLASS_CONFIG = "key.serializer";
value.serializer
用于序列化消息值的序列化器类
public static final String VALUE_SERIALIZER_CLASS_CONFIG = "value.serializer";
connections.max.idle.ms
客户端与服务器保持空闲连接的最长时间(毫秒)。默认值为 540000(即 9 分钟)。例如:
"900000"
表示客户端与服务器保持空闲连接的最长时间为 15 分钟
public static final String CONNECTIONS_MAX_IDLE_MS_CONFIG = "connections.max.idle.ms";
partitioner.class
用于指定消息将被发送到哪个分区的算法,即分区器的实现类。Kafka 中的主题(topic)通常被划分为多个分区,每个分区都包含有序的消息序列。分区器决定了生产者发送的消息应该被分配到哪个分区中。
通过配置
partitioner.class
,用户可以自定义分区算法,以满足特定的业务需求。Kafka 提供了默认的分区器,也允许用户根据自己的逻辑实现自定义的分区器。例如,以下是配置
partitioner.class
的示例:partitioner.class=com.example.CustomPartitioner
- 1
- 2
- 3
在这个示例中,
com.example.CustomPartitioner
是用户自定义的分区器类的全限定名。该类必须实现 Kafka 提供的org.apache.kafka.clients.producer.Partitioner
接口,该接口定义了确定消息应该被发送到哪个分区的方法。自定义分区器可以根据消息的内容、键(如果有)、以及其他上下文信息,灵活地决定消息应该被发送到哪个分区。这样的自定义分区策略可以帮助实现一些特定的业务逻辑,例如确保相关的消息被发送到相同的分区,以提高消费的局部性。
在没有显式配置
partitioner.class
的情况下,Kafka 使用默认的分区器,该分区器根据消息的键(如果有)或者采用轮询的方式将消息平均分配到所有分区。
public static final String PARTITIONER_CLASS_CONFIG = "partitioner.class";
interceptor.classes
用于指定一组拦截器类。拦截器类是实现 Kafka 接口
org.apache.kafka.clients.producer.ProducerInterceptor
或者org.apache.kafka.clients.consumer.ConsumerInterceptor
的类,用于在生产者或消费者发送或接收消息之前或之后对消息进行处理。拦截器允许用户对消息进行自定义的预处理或后处理。这些操作可以包括但不限于:
- 对消息进行加工、转换、过滤。
- 在消息发送或接收之前或之后记录日志。
- 对消息的时间戳或键进行修改。
通过配置
interceptor.classes
参数,可以指定一组拦截器类,并且它们将按顺序应用于每个消息。这样的拦截器链使得在消息处理过程中可以执行多个不同的操作。例如,以下是配置
interceptor.classes
的示例:interceptor.classes=com.example.MyProducerInterceptor, com.example.MyConsumerInterceptor
- 1
- 2
- 3
在这个示例中,
com.example.MyProducerInterceptor
和com.example.MyConsumerInterceptor
是用户定义的拦截器类的全限定名。这两个类必须分别实现 Kafka 提供的org.apache.kafka.clients.producer.ProducerInterceptor
和org.apache.kafka.clients.consumer.ConsumerInterceptor
接口。需要注意的是,拦截器类的顺序很重要。拦截器将按照它们在
interceptor.classes
参数中声明的顺序依次应用于每个消息。如果需要确保拦截器按照特定的顺序应用,可以通过配置参数来指定顺序。拦截器提供了一种灵活的方式来实现特定的消息处理逻辑,同时也允许用户对消息进行监控和记录。
public static final String INTERCEPTOR_CLASSES_CONFIG = "interceptor.classes";
enable.idempotence
public static final String ENABLE_IDEMPOTENCE_CONFIG = "enable.idempotence";
transaction.timeout.ms
public static final String TRANSACTION_TIMEOUT_CONFIG = "transaction.timeout.ms";
transactional.id
用于启用生产者的幂等性。幂等性是指对于同一个生产者实例,无论消息发送多少次,最终只会产生一条副本(实际上是一个幂等序列)的性质。这可以防止由于网络错误、重试或者生产者重新启动等情况导致的重复消息。
启用生产者的幂等性可以通过设置
enable.idempotence
参数为true
来实现。例如:enable.idempotence=true
- 1
- 2
- 3
启用幂等性会自动设置一些与幂等性相关的配置,例如:
acks
配置将被设置为 “all”,确保所有的 ISR(In-Sync Replicas)都已经接收到消息。max.in.flight.requests.per.connection
将被设置为 1,以确保在一个连接上只有一个未确认的请求。幂等性对于确保消息传递的精确一次语义非常重要。在启用幂等性的情况下,生产者会为每条消息分配一个唯一的序列号,以便在重试发生时 Broker 能够正确地识别并去重重复的消息。
需要注意的是,启用幂等性会对性能产生一些开销,因为它引入了额外的序列号和一些额外的网络开销。在生产环境中,需要仔细评估幂等性对性能的影响,并根据实际需求权衡性能和可靠性。
public static final String TRANSACTIONAL_ID_CONFIG = "transactional.id";
security.providers
参数已经被 Kafka 移除了。在较早的 Kafka 版本中,这个参数可能被用于指定安全性相关的提供者。然而,从 Kafka 2.0 开始,Kafka 已经采用了基于 JAAS(Java Authentication and Authorization Service)的身份验证和授权机制,这个参数不再被使用。
现在,Kafka 的安全性配置主要包括以下几个方面:
- 身份验证机制(Authentication Mechanisms):Kafka 支持多种身份验证机制,如SSL/TLS、SASL(Simple Authentication and Security Layer)、OAuth等。通过配置
security.protocol
参数选择所需的身份验证机制。- 授权机制(Authorization Mechanisms):Kafka 使用 ACL(Access Control Lists)来控制对主题和分区的访问权限。可以通过配置
authorizer.class.name
参数选择 ACL 的实现类。- 加密通信(Encryption):可以通过配置 SSL/TLS 来对 Kafka 通信进行加密,以保护数据在传输过程中的安全性。
- 客户端配置(Client Configuration):客户端需要根据服务端的安全配置进行相应的配置,如设置 SSL/TLS 的信任证书、SASL 的认证信息等。
需要根据具体的安全需求和环境配置 Kafka 的安全性参数。建议查阅最新版本的 Kafka 文档以获取详细的安全配置指南。
public static final String SECURITY_PROVIDERS_CONFIG = "security.providers";
retry.backoff.ms
用于定义在发生可重试的发送错误后,生产者在进行重试之前等待的时间间隔,以毫秒为单位。
当生产者发送消息到 Kafka 时,可能会遇到一些可重试的错误,例如网络问题、Kafka 服务器繁忙等。retry.backoff.ms 允许在出现这些可重试错误后等待一段时间,然后再次尝试发送消息,以避免频繁的重试。这样的设计有助于在短时间内解决暂时性的问题,而不至于对 Kafka 服务器造成额外的负担。
具体而言,如果发生了可重试的错误,生产者将等待 retry.backoff.ms 指定的时间间隔,然后进行下一次重试。如果重试依然失败,生产者可能会继续进行更多的重试,每次之间间隔逐渐增加,以避免过度压力和频繁的连接尝试。
默认情况下,retry.backoff.ms 的值通常是 100 毫秒,但可以根据实际需求和环境进行调整
public static final String RETRY_BACKOFF_MS_CONFIG = "retry.backoff.ms";
compression.type
控制发送到 Kafka 的消息是否压缩。可以是“none”、“gzip”、“snappy”或“lz4”
public static final String COMPRESSION_TYPE_CONFIG = "compression.type";
metrics.sample.window.ms
用于配置 Kafka Broker 的参数,用于定义度量指标(metrics)的采样窗口的时间跨度,以毫秒为单位。
具体来说,这个参数指定了度量指标的采样窗口的持续时间。在这个时间段内,Kafka Broker 会收集和计算各种指标,比如吞吐量、延迟、请求处理时间等。然后,这些度量指标可以被监控工具或者外部系统使用,以便实时地监控 Kafka Broker 的运行状态和性能指标。
通过调整
metrics.sample.window.ms
这个参数,可以改变度量指标采样的时间窗口长度,以适应不同的监控和性能分析需求。较短的采样窗口可以提供更加实时的性能指标,但也会增加系统资源的开销;而较长的采样窗口则可以减少资源开销,但会牺牲一些实时性。默认情况下,
metrics.sample.window.ms
的值通常是 30000 毫秒(30秒),但根据具体的 Kafka 集群配置和监控需求,可以进行调整。
public static final String METRICS_SAMPLE_WINDOW_MS_CONFIG = "metrics.sample.window.ms";
metrics.num.samples
用于配置 Kafka Broker 的参数,用于指定在每个度量指标采样窗口中收集的样本数量。
具体来说,度量指标(metrics)是用于监视 Kafka Broker 运行状态和性能的关键数据,比如吞吐量、延迟、请求处理时间等。而
metrics.num.samples
参数则控制了在每个采样窗口内收集多少个样本。这些样本可以用于计算度量指标的平均值、最大值、最小值等统计信息。通过调整
metrics.num.samples
这个参数,可以平衡度量指标的准确性和资源消耗之间的权衡。较大的样本数量可以提供更加准确的度量指标统计信息,但会增加系统资源的开销;而较小的样本数量则可以减少资源消耗,但可能会牺牲一些准确性。默认情况下,
metrics.num.samples
的值通常是 2,但根据具体的 Kafka 集群配置和监控需求,可以进行调整。
public static final String METRICS_NUM_SAMPLES_CONFIG = "metrics.num.samples";
metrics.recording.level
用于配置度量指标(metrics)的记录级别。这个参数决定了哪些度量指标会被记录和汇报。
具体来说,
metrics.recording.level
可以设置为以下几个级别之一:
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
通过调整
metrics.num.samples
这个参数,可以平衡度量指标的准确性和资源消耗之间的权衡。较大的样本数量可以提供更加准确的度量指标统计信息,但会增加系统资源的开销;而较小的样本数量则可以减少资源消耗,但可能会牺牲一些准确性。默认情况下,
metrics.num.samples
的值通常是 2,但根据具体的 Kafka 集群配置和监控需求,可以进行调整。
public static final String METRICS_NUM_SAMPLES_CONFIG = "metrics.num.samples";
metrics.recording.level
用于配置度量指标(metrics)的记录级别。这个参数决定了哪些度量指标会被记录和汇报。
具体来说,
metrics.recording.level
可以设置为以下几个级别之一:
[外链图片转存中…(img-qSLtvV8y-1715712041202)]
[外链图片转存中…(img-y3VqVvE0-1715712041203)]
[外链图片转存中…(img-DsOTxwR7-1715712041203)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。