Kafka(二、Kafka生产者 - 向kafka写入数据)

5 篇文章 1 订阅

Kakfa 生产者配置

由于配置太多,在此不一一列举,只显示使用率最高的几个配置,其他配置请参考官网。
http://kafka.apache.org/documentation/#producerconfigs

NAMEDESCRIPTIONTYPEDEFAULTVALID VALUES
key.serializerkey序列化,可以使用Kafka默认的序列化和自定义序列化器class
value.serializervalue序列化,可以使用Kafka默认的序列化和自定义序列化器
acks生产者需要leader确认请求完成之前接收的应答数。此配置控制了发送记录的持久性。允许以下设置:acks=0 如果设置为0,那么生产者将不等待任何消息确认。消息将立刻添加到socket缓冲区并考虑发送。在这种情况下不能保障消息被服务器接收到。并且重试机制不会生效(因为客户端不知道故障了没有)。每个消息返回的offset始终设置为-1。acks=1,这意味着leader写入消息到本地日志就立即响应,而不等待所有follower应答。在这种情况下,如果响应消息之后但follower还未复制之前leader立即故障,那么消息将会丢失。acks=all 这意味着leader将等待所有副本同步后应答消息。此配置保障消息不会丢失(只要至少有一个同步的副本)。这是最强壮的可用性保障。等价于acks=-1。string1[all, -1, 0, 1]
bootstrap.servershost/port列表,用于初始化建立和Kafka集群的连接。列表格式为host1:port1,host2:port2,…,无需添加所有的集群地址,kafka会根据提供的地址发现其他的地址(你可以多提供几个,以防提供的服务器关闭)list“”non-null string
buffer.memory生产者用来缓存等待发送到服务器的消息的内存总字节数。如果消息发送比可传递到服务器的快,生产者将阻塞max.block.ms之后,抛出异常。此设置应该大致的对应生产者将要使用的总内存,但不是硬约束,因为生产者所使用的所有内存都用于缓冲。一些额外的内存将用于压缩(如果启动压缩),以及用于保持发送中的请求。一个合理的内存大小。long33554432[0,…]
compression.type生产者生成的所有数据的压缩类型。默认值为无(即不压缩)。有效值为nonegzipsnappylz4,或zstd。压缩是指全部数据的压缩,因此,批处理的效率也会影响压缩率(批处理越多意味着压缩越好)。stringnone
retries设置一个比零大的值,客户端如果发送失败则会重新发送。注意,这个重试功能和客户端在接到错误之后重新发送没什么不同。如果max.in.flight.requests.per.connection没有设置为1,有可能改变消息发送的顺序,因为如果2个批次发送到一个分区中,并第一个失败了并重试,但是第二个成功了,那么第二个批次将超过第一个。“retries”和“retries.backoff.ms”决定了重试机制,也就是如果一个请求失败了可以重试几次,每次重试的间隔是多少毫秒。这个大家适当设置几次重试的机会,给一定的重试间隔即可,比如给100ms的重试间隔。 int2147483647[0,…,2147483647]
batch.size当多个消息要发送到相同分区的时,生产者尝试将消息批量打包在一起,以减少请求交互。这样有助于客户端和服务端的性能提升。该配置的默认批次大小(以字节为单位):不会打包大于此配置大小的消息。发送到broker的请求将包含多个批次,每个分区一个,用于发送数据。int16384[0,…]
ssl.key.password密钥存储文件中私钥的密码。这对于客户端是可选的。passwordnull
ssl.keystore.location密钥存储文件的位置这对于客户端是可选的,可以用于客户端的双向身份验证。stringnull
ssl.keystore.password密钥存储文件的存储密码。这对于客户端是可选的,并且仅在配置了ssl.keystore.location时才需要。passwordnull
ssl.truststore.location信任存储和文件的位置。stringnull
ssl.truststore.password信任存储文件的密码。如果未设置密码,则仍然可以访问信任库,但是将禁用完整性检查。passwordnull

代码示例

这里没有使用最后几个ssl配置,内网默认都是网络安全的。

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.Properties;

public class ProducerDemo {

    private final KafkaProducer<String, String> producer;

    public final static String TOPIC = "test5";

    private ProducerDemo() {
        Properties props = new Properties();

        props.put("bootstrap.servers", "127.0.0.1:9092");
        // 所有follower都响应了才认为消息提交成功,即"committed"
        props.put("acks", "all");
        // retries = MAX 无限重试,直到你意识到出现了问题:)
        props.put("retries", 0);
        // producer将试图批处理消息记录,以减少请求次数.默认的批量处理消息字节数
        props.put("batch.size", 16384);
        // batch.size当批量的数据大小达到设定值后,就会立即发送,不顾下面的linger.ms,
        //  延迟1ms发送,这项设置将通过增加小的延迟来完成--即,不是立即发送一条记录,producer将会等待给定的延迟时间以允许其他消息记录发送,这些消息记录可以批量处理
        props.put("linger.ms", 1);
        // producer可以用来缓存数据的内存大小。
        props.put("buffer.memory", 33554432);
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        producer = new KafkaProducer<>(props);
    }

    public void produce() {
        int messageNo = 1;
        final int COUNT = 5;

        while (messageNo < COUNT) {

            String key = String.valueOf(messageNo);
            String data = String.format("hello KafkaProducer message %s from hubo 06291018 ", key);

            try {
                // 返回值为Future,现在为不关心是否发送成功。还有同步发送,异步发送两种。
                producer.send(new ProducerRecord<String, String>(TOPIC,",", data));
            } catch (Exception e) {
                e.printStackTrace();
            }

            messageNo++;
        }

        producer.close();
    }

    public static void main(String[] args) {
        new ProducerDemo().produce();
    }
}

自定义分区器
首先自定义个分区器,一定要实现Partitioner接口。


import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import org.apache.kafka.common.PartitionInfo;
import org.apache.kafka.common.record.InvalidRecordException;
import org.apache.kafka.common.utils.Utils;

import java.util.List;
import java.util.Map;

public class CustomPartitioner implements Partitioner {

    String keyName;

    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
        List<PartitionInfo> partitionInfos = cluster.partitionsForTopic(topic);
        int numPartitions = partitionInfos.size();

        if ((keyBytes == null) || (!(key instanceof String))) {
            throw new InvalidRecordException("We expect all messages to have customer name as key");
        }

        if (((String) key).equalsIgnoreCase(keyName)) {
            return numPartitions;
        }

        return (Math.abs(Utils.murmur2(keyBytes))) % (numPartitions - 1);

    }

    @Override
    public void close() {

    }

    @Override
    public void configure(Map<String, ?> configs) {
        keyName = (String) configs.get("");
    }
}

然后将自定义分区器添加到配置中:

        //设置自定义分区
        props.put("partitioner.class", "com.study.Kafka.common.CustomPartitioner");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 下面是一个简单的 Flink 应用程序,将 Kafka 主题中的数据读取并写入到另一个 Kafka 主题: ```java import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; import org.apache.flink.streaming.connectors.kafka.KafkaSerializationSchema; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.serialization.StringSerializer; import java.util.Properties; public class KafkaToFlinkToFlinkKafka { public static void main(String[] args) throws Exception { // set up the execution environment final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // configure Kafka consumer Properties consumerProps = new Properties(); consumerProps.setProperty("bootstrap.servers", "localhost:9092"); consumerProps.setProperty("group.id", "test-group"); // create a Kafka consumer data source FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>("input-topic", new SimpleStringSchema(), consumerProps); // read from Kafka DataStream<String> stream = env.addSource(consumer); // configure Kafka producer Properties producerProps = new Properties(); producerProps.setProperty("bootstrap.servers", "localhost:9092"); // create a Kafka producer sink FlinkKafkaProducer<String> producer = new FlinkKafkaProducer<>("output-topic", new KafkaSerializationSchema<String>() { @Override public ProducerRecord<byte[], byte[]> serialize(String s, Long aLong) { return new ProducerRecord<>("output-topic", s.getBytes()); } }, producerProps, FlinkKafkaProducer.Semantic.EXACTLY_ONCE); // write to Kafka stream.addSink(producer); // execute the Flink job env.execute("Kafka to Flink to Kafka"); } } ``` 在上面的代码中,我们首先创建了一个 `StreamExecutionEnvironment` 对象,然后使用 Kafka 的消费者API读取一个名为 `input-topic` 的 Kafka 主题中的数据,并将其转换为 Flink 数据流。接下来,我们创建一个 Kafka 生产者,并将数据写入名为 `output-topic` 的 Kafka 主题。最后,我们调用 `env.execute()` 来启动 Flink 作业。 请注意,上面的代码只是一个简单的入门级示例。在生产环境中,您可能需要更复杂的逻辑来处理数据并将其写入 Kafka 主题。 ### 回答2: Flink是一个流处理框架,它可以处理流式数据,并且可以与Kafka等消息队列相结合,实现数据的实时处理和分析。下面是一个使用Flink将Kafka数据写入Kafka的入门级示例。 首先,我们需要引入Flink和Kafka的相关依赖包,并创建一个Flink程序入口。 ``` import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.producer.ProducerConfig; import java.util.Properties; public class KafkaToKafkaDemo { public static void main(String[] args) throws Exception { // 创建Flink程序入口 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 设置Kafka的相关配置 Properties properties = new Properties(); properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka1:9092,kafka2:9092,kafka3:9092"); properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "flink-consumer"); properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka1:9092,kafka2:9092,kafka3:9092"); // 创建Kafka消费者 FlinkKafkaConsumer<String> kafkaConsumer = new FlinkKafkaConsumer<>("input-topic", new SimpleStringSchema(), properties); // 添加Kafka消费者到Flink程序中 DataStream<String> input = env.addSource(kafkaConsumer); // 创建Kafka生产者 FlinkKafkaProducer<String> kafkaProducer = new FlinkKafkaProducer<>("output-topic", new SimpleStringSchema(), properties); // 将输入数据写入Kafka input.addSink(kafkaProducer); // 执行Flink程序 env.execute("Kafka to Kafka Demo"); } } ``` 上述代码中,我们首先创建了一个Flink程序入口,然后设置了连接Kafka所需的配置信息。之后,我们创建了一个Kafka消费者,并将其添加到Flink程序中。接着,我们创建了一个Kafka生产者,并将输入的数据写入Kafka中。最后,我们执行了Flink程序。 需要注意的是,在上述代码中,我们需要将`kafka1:9092,kafka2:9092,kafka3:9092`替换为实际的Kafka集群地址,`input-topic`和`output-topic`替换为实际的输入和输出主题名称。 这是一个简单的入门级示例,演示了如何使用Flink将Kafka数据写入Kafka。你可以根据自己的需求,在此基础上进行更复杂的流处理操作。 ### 回答3: Flink是一个流计算引擎,可以用来处理大规模的实时数据流。而Kafka是一种高吞吐量的分布式消息队列,常用于构建数据流处理平台。那么如果想要将Kafka中的数据写入到另一个Kafka集群中,可以使用Flink来实现。下面是一个入门级的示例代码,演示了如何使用Java编写一个简单的Flink作业来实现将Kafka数据写入到另一个Kafka集群中。 首先,需要在项目的pom.xml文件中添加Flink和Kafka相关的依赖: ```xml <dependencies> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java_2.12</artifactId> <version>1.11.2</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <<artifactId>flink-connector-kafka_2.12</artifactId> <version>1.11.2</version> </dependency> </dependencies> ``` 接下来,可以编写一个简单的Flink作业,该作业从一个Kafka主题中消费数据,并将其写入到另一个Kafka主题中: ```java import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; import org.apache.flink.streaming.connectors.kafka.internals.KafkaSerializationSchemaWrapper; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerRecord; import java.util.Properties; public class KafkaToFlinkToFlinkKafkaDemo { public static void main(String[] args) throws Exception { // 创建执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 设置Kafka消费者的配置 Properties consumerProps = new Properties(); consumerProps.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka_source:9092"); consumerProps.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "flink-consumer"); // 创建一个从Kafka读取数据数据流 DataStream<String> kafkaSource = env .addSource(new FlinkKafkaConsumer<>("input_topic", new SimpleStringSchema(), consumerProps)); // 设置Kafka生产者的配置 Properties producerProps = new Properties(); producerProps.setProperty("bootstrap.servers", "kafka_target:9092"); // 创建一个写入Kafka数据流 // 注意:这里将消息序列化为字符串,所以消费者也需要使用相同的字符串序列化器来读取数据 DataStream<String> kafkaSink = kafkaSource .addSink(new FlinkKafkaProducer<>("output_topic", new KafkaSerializationSchemaWrapper<>(new SimpleStringSchema()), producerProps)); // 执行作业并等待任务完成 env.execute("Kafka to Flink to Kafka Demo"); } } ``` 在上述代码中,首先通过FlinkKafkaConsumer创建一个从Kafka中读取数据数据流,然后通过FlinkKafkaProducer创建一个将数据写入Kafka中的数据流。注意,需要为消费者和生产者配置正确的Kafka集群地址和主题名称。 以上就是一个简单的使用Flink将Kafka数据写入到另一个Kafka集群的示例。当然,实际应用中还需要考虑更多的业务需求和数据转换操作。希望对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值