kafka producer 初始化

1、设置分区器
2、设置序列化器
3、设置拦截器
4、创建集群Metadata,并定时更新
5、设置压缩格式
6、创建RecordAccumulator
7、创建NetworkClient
8、创建Sender线程并启动

producer = new KafkaProducer<>(props);
-> 
 //1、设置分区器
 this.partitioner = config.getConfiguredInstance(ProducerConfig.PARTITIONER_CLASS_CONFIG, Partitioner.class);
 //重试时间 retry.backoff.ms 默认100ms
 long retryBackoffMs = config.getLong(ProducerConfig.RETRY_BACKOFF_MS_CONFIG);
 //2、设置序列化器
     ...
 //3、设置拦截器
 List<ProducerInterceptor<K, V>> interceptorList = (List) (new   ProducerConfig(userProvidedConfigs)).getConfiguredInstances(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,
                    ProducerInterceptor.class);
            this.interceptors = interceptorList.isEmpty() ? null : new ProducerInterceptors<>(interceptorList);

 /**4、生产者从服务端那儿拉取过来的kafka的元数据。
 //生产者要想去拉取元数据, 发送网络请求,重试,
 //metadata.max.age.ms(默认5分钟)
 //生产者每隔一段时间都要去更新一下集群的元数据。*/
 this.metadata = new Metadata(retryBackoffMs, config.getLong(ProducerConfig.METADATA_MAX_AGE_CONFIG), true, clusterResourceListeners);

 /**max.request.size 生产者往服务端发送消息的时候,规定一条消息最大多大?
  //如果你超过了这个规定消息的大小,你的消息就不能发送过去。
  //默认是1M,这个值偏小,在生产环境中,我们需要修改这个值。
  //经验值是10M。但是大家也可以根据自己公司的情况来。*/
  this.maxRequestSize = config.getInt(ProducerConfig.MAX_REQUEST_SIZE_CONFIG);
  
   //指的是缓存大小 RecordAccumulator 大小
   //buffer.memory 默认值是32M,这个值一般是够用,如果有特殊情况的时候,我们可以去修改这个值。
   this.totalMemorySize = config.getLong(ProducerConfig.BUFFER_MEMORY_CONFIG);

/**5、kafka是支持压缩数据的,这儿设置压缩格式。
//提高你的系统的吞吐量,你可以设置压缩格式。
//一次发送出去的消息就更多。生产者这儿会消耗更多的cpu.*/
this.compressionType = CompressionType.forName(config.getString(ProducerConfig.COMPRESSION_TYPE_CONFIG));

//TODO 6、 创建了一个核心的组件 RecordAccumulator
 this.accumulator = new RecordAccumulator(config.getInt(ProducerConfig.BATCH_SIZE_CONFIG),
         this.totalMemorySize,
         this.compressionType,
         config.getLong(ProducerConfig.LINGER_MS_CONFIG),
         retryBackoffMs,
         metrics,
         time); 
                    
/**去更新元数据  同4
//addresses 这个地址其实就是我们写producer代码的时候,传参数的时候,传进去了一个broker的地址。
//所以这段代码看起来像是去服务端拉取元数据,所以我们去验证一下,是否真的去拉取元数据。
//TODO update方法初始化的时候并没有去服务端拉取元数据。*/
this.metadata.update(Cluster.bootstrap(addresses), time.milliseconds());
ChannelBuilder channelBuilder = ClientUtils.createChannelBuilder(config.values());

/**
 * TODO 7、 初始化了一个重要的管理网路的组件 NetworkClient。
  *  (1)connections.max.idle.ms: 默认值是9分钟
  *      一个网络连接最多空闲多久,超过这个空闲时间,就关闭这个网络连接。
  *
  *  (2)max.in.flight.requests.per.connection:默认是5
  *    producer向broker发送数据的时候,其实是有多个网络连接。
  *    每个网络连接可以忍受 producer端发送给broker 消息然后消息没有响应的个数。
  *
  *    因为kafka有重试机制,所以有可能会造成数据乱序,如果想要保证有序,这个值要把设置为1.
  *    相当于一条一条的发送,每条发送成功并返回再发别的消息
  *
  * (3)send.buffer.bytes:socket发送数据的缓冲区的大小,默认值是128K
  * (4)receive.buffer.bytes:socket接受数据的缓冲区的大小,默认值是32K。
   */
 NetworkClient client = new NetworkClient(
         new Selector(config.getLong(ProducerConfig.CONNECTIONS_MAX_IDLE_MS_CONFIG), this.metrics, time, "producer", channelBuilder),
         this.metadata,
         clientId,
         config.getInt(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION),
         config.getLong(ProducerConfig.RECONNECT_BACKOFF_MS_CONFIG),
         config.getInt(ProducerConfig.SEND_BUFFER_CONFIG),
         config.getInt(ProducerConfig.RECEIVE_BUFFER_CONFIG),
         this.requestTimeoutMs, time);

 /***
  *  8、创建sender线程 并启动
  *   这个就是一个线程
     * 我们在项目中一般都会去设置重试,
     *
     * (1) retries:重试的次数
     * (2) acks:
     *   0:
     *      producer发送数据到broker后,就完了,没有返回值,不管写成功还是写失败都不管了。
     *   1:
     *      producer发送数据到broker后,数据成功写入leader partition以后返回响应。
     *      当刚写完leader partition 并发送响应后leader挂了,follower未拉取到数据就会进行重新选举,造成数据丢失
     *
     *   -1:
     *       producer发送数据到broker后,数据要写入到leader partition里面,并且数据同步到所有的
     *       follower partition里面以后,才返回响应。
     *       这种情况下,当无follower时会丢数,保证有多个副本时才能保证不丢数据
     *
     */
    this.sender = new Sender(client,
            this.metadata,
            this.accumulator,
            config.getInt(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION) == 1,
            config.getInt(ProducerConfig.MAX_REQUEST_SIZE_CONFIG),
            (short) parseAcks(config.getString(ProducerConfig.ACKS_CONFIG)),
            config.getInt(ProducerConfig.RETRIES_CONFIG),
            this.metrics,
            new SystemTime(),
            clientId,
            this.requestTimeoutMs);
   //启动线程。
   this.ioThread.start();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值