kafka优化(系列四):kafka配置优化和kafka批量消费,提高分区数量

2024-08-28 04:48

本文主要是介绍kafka优化(系列四):kafka配置优化和kafka批量消费,提高分区数量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

往期精选

  • 第一篇我们讲到了docker的单机搭建。

  • 第二篇我们讲到了与springboot的整合。

  • 第三篇我们讲到了kafka的原理。

    这一篇我们将叙述,我是怎么在项目中进行对kafka优化的我们将从三方面进行考虑,一是代码;二是    配置;三是集群。项目背景,做数据迁移工作后面我将写几篇文章讲诉我们是怎么对百万数据进行迁移的工作)。主要场景利用kafka做读写分离,一直请求源数据写入到kafka生产者,然后kafka消费者进行写入数据到新数据。

一、配置优化《报错》节选:

[2018-09-25 11:23:59.370] ERROR [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] LoggingErrorHandler.java:37 - Error while processing: nullorg.apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing the session timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.sendOffsetCommitRequest(ConsumerCoordinator.java:722)at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.commitOffsetsSync(ConsumerCoordinator.java:600)at org.apache.kafka.clients.consumer.KafkaConsumer.commitSync(KafkaConsumer.java:1250)at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.commitIfNecessary(KafkaMessageListenerContainer.java:1324)at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.processCommits(KafkaMessageListenerContainer.java:1185)at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:688)at java.util.concurrent.Executors$RunnableAdapter.call$$$capture(Executors.java:511)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java)at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)at java.util.concurrent.FutureTask.run(FutureTask.java)at java.lang.Thread.run(Thread.java:748)

这是由于kafka一直生产数据,导致kafka消费太慢了。我们主要优化也是对消费者进行优化。根据上面的报错,我们可以看到一个参数:max-poll-records,所以我们首先将对提交数,进行调大。具体的需要根据项目进行测试,我们把数进行调大到100,同时对下面的参数进行:

#自动提交offset到zookeeper的时间间隔

auto-commit-interval: 1000

#earliest 

#当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 

#latest 

#当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 

#none 

#topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常

auto-offset-reset: latest

#提交方式改为false,是否自动周期性提交已经拉取到消费端的消息offset

enable-auto-commit: false

由于使用了spring-kafka,则把kafka-client的enable.auto.commit设置成了false,表示禁止kafka-client自动提交offset,因为就是之前的自动提交失败,导致offset永远没更新,从而转向使用spring-kafka的offset提交机制。并且spring-kafka提供了多种提交策略:

  然后我修改了kafka的配置(spring-kafka),需要到安装的文件(config)下进行修改,分别是生产文件和配置文件。

1.session.timeout.ms=100000(增大session超时时间)。

2.request.timeout.ms=110000(socket握手超时时间,默认是3000 但是kafka配置要求大于session.timeout.ms时间).

同时Kafka的生产端可以压缩消息,如果原始消息是XML,当通过压缩之后,消息可能会变得不那么大。在生产端的配置参数中使用compression.codec和commpressed.topics可以开启压缩功能,压缩算法可以使用GZip或Snappy。

二、代码优化:《日志》节选

如果进行了的配置调优,差不多会提高kafka的消费能力,但是写入过大,控制台还是打印下面日志信息:

2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] LogContext.java:341 - [Consumer clientId=consumer-4, groupId=test-consumer-group] Revoking previously assigned partitions [XXXXX-0][2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#2-0-C-1] LogContext.java:341 - [Consumer clientId=consumer-1, groupId=test-consumer-group] Revoking previously assigned partitions [XXXXX-0][2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#4-0-C-1] LogContext.java:341 - [Consumer clientId=consumer-3, groupId=test-consumer-group] Revoking previously assigned partitions [XXXXXX-0][2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] AbstractMessageListenerContainer.java:343 - partitions revoked: [XXXX-0][2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#2-0-C-1] AbstractMessageListenerContainer.java:343 - partitions revoked: [XXXXXX-0][2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#4-0-C-1] AbstractMessageListenerContainer.java:343 - partitions revoked: [XXXXXX-0][2018-09-25 14:39:53.193] INFO [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] LogContext.java:336 - [Consumer clientId=consumer-4, groupId=test-consumer-group] 

也是就说机制一直打印这些信息,但是又不报错,但是又不写入数据,我们就想,除了配置优化之后,能不能像数据库一样,批量提交或者说是批量消费呢?看了官网资料,发现确实可以,以下是我们对代码的优化,由单一的消费,改为批量消费:

一:增加一个config类。

@Configuration
@EnableKafkapublic class KafkaConfig {@Beanpublic KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();factory.setConsumerFactory(consumerFactory());factory.setConcurrency(10);factory.getContainerProperties().setPollTimeout(1500);factory.setBatchListener(true);//@KafkaListener 批量消费  每个批次数量在Kafka配置参数中设置ConsumerConfig.MAX_POLL_RECORDS_CONFIGfactory.getContainerProperties().setAckMode(AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIATE);//设置提交偏移量的方式return factory;}public ConsumerFactory<String, String> consumerFactory() {return new DefaultKafkaConsumerFactory<>(consumerConfigs());}public Map<String, Object> consumerConfigs() {Map<String, Object> propsMap = new HashMap<>(16);propsMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "IP地址需要修改");propsMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);propsMap.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 1000);propsMap.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 100000);propsMap.put(ConsumerConfig.REQUEST_TIMEOUT_MS_CONFIG,110000);propsMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);propsMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);propsMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test-consumer-group");propsMap.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");propsMap.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 150);//每个批次获取数return propsMap;}}

二、更改消费接受代码。

 @KafkaListener(topics = {"消费名称需要改"})public void listen(List<ConsumerRecord> records, Acknowledgment ack) {try {for (ConsumerRecord record : records) {Optional<?> kafkaMessage = Optional.ofNullable(record.value());if (kafkaMessage.isPresent()) {Object message = kafkaMessage.get();log.info("----------------- record =" + record);log.info("------------------ message =" + message);}}} catch (Exception e) {log.error("kafka失败,当前失败的批次。data:{}", records);e.printStackTrace();} finally {ack.acknowledge();}}

集群搭建

前面虽然优化配置和代码,但是代码执行还是不够快,网上寻找资料(提高了partition的数量,从而提高了consumer的并行能力,从而提高数据的消费能力),说可以提高分区数量,如果单机怎么提高还是一样的(我们试过了),后来搭建了一个集群。注意我们是使用docker搭建kafka集群的,搭建过程如下。docker-compose.yml内容:

version: '2'services:zookeeper:image: wurstmeister/zookeeperports:- "2181:2181"kafka:image: wurstmeister/kafkaports:- "9095:9095"environment:KAFKA_ADVERTISED_HOST_NAME: IP地址KAFKA_ADVERTISED_PORT: 9095KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://XXXXXXXX:9095KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9095KAFKA_DELETE_TOPIC_ENABLE: "true"KAFKA_LOG_RETENTION_HOURS: 1KAFKA_MESSAGE_MAX_BYTES: 10000000KAFKA_REPLICA_FETCH_MAX_BYTES: 10000000KAFKA_GROUP_MAX_SESSION_TIMEOUT_MS: 100000KAFKA_NUM_PARTITIONS: 2KAFKA_DELETE_RETENTION_MS: 1000KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- /var/run/docker.sock:/var/run/docker.sockkafka-manager:image: sheepkiller/kafka-managerlinks:- kafka- zookeeperenvironment:ZK_HOSTS: zookeeper:2181APPLICATION_SECRET: letmeinKM_ARGS: -Djava.net.preferIPv4Stack=trueports:- "9000:9000"

1.启动的命令:

docker-compose up -d

2.先去修改配置文件的端口,然后再启动相关的命令:

docker-compose scale kafka=2

3.再次修改文件袋的端口,然后再启动相关的命令:

docker-compose scale kafka=3

以上就是我所总结的kafka优化,欢迎有更好的方案进行交流,欢迎关注微信号:繁荣Aaron和转发。

这篇关于kafka优化(系列四):kafka配置优化和kafka批量消费,提高分区数量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113773

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Linux云服务器手动配置DNS的方法步骤

《Linux云服务器手动配置DNS的方法步骤》在Linux云服务器上手动配置DNS(域名系统)是确保服务器能够正常解析域名的重要步骤,以下是详细的配置方法,包括系统文件的修改和常见问题的解决方案,需要... 目录1. 为什么需要手动配置 DNS?2. 手动配置 DNS 的方法方法 1:修改 /etc/res

mysql8.0.43使用InnoDB Cluster配置主从复制

《mysql8.0.43使用InnoDBCluster配置主从复制》本文主要介绍了mysql8.0.43使用InnoDBCluster配置主从复制,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录1、配置Hosts解析(所有服务器都要执行)2、安装mysql shell(所有服务器都要执行)3、

java程序远程debug原理与配置全过程

《java程序远程debug原理与配置全过程》文章介绍了Java远程调试的JPDA体系,包含JVMTI监控JVM、JDWP传输调试命令、JDI提供调试接口,通过-Xdebug、-Xrunjdwp参数配... 目录背景组成模块间联系IBM对三个模块的详细介绍编程使用总结背景日常工作中,每个程序员都会遇到bu

Ubuntu向多台主机批量传输文件的流程步骤

《Ubuntu向多台主机批量传输文件的流程步骤》:本文主要介绍在Ubuntu中批量传输文件到多台主机的方法,需确保主机互通、用户名密码统一及端口开放,通过安装sshpass工具,准备包含目标主机信... 目录Ubuntu 向多台主机批量传输文件1.安装 sshpass2.准备主机列表文件3.创建一个批处理脚

JDK8(Java Development kit)的安装与配置全过程

《JDK8(JavaDevelopmentkit)的安装与配置全过程》文章简要介绍了Java的核心特点(如跨平台、JVM机制)及JDK/JRE的区别,重点讲解了如何通过配置环境变量(PATH和JA... 目录Java特点JDKJREJDK的下载,安装配置环境变量总结Java特点说起 Java,大家肯定都

MySQL批量替换数据库字符集的实用方法(附详细代码)

《MySQL批量替换数据库字符集的实用方法(附详细代码)》当需要修改数据库编码和字符集时,通常需要对其下属的所有表及表中所有字段进行修改,下面:本文主要介绍MySQL批量替换数据库字符集的实用方法... 目录前言为什么要批量修改字符集?整体脚本脚本逻辑解析1. 设置目标参数2. 生成修改表默认字符集的语句3

linux配置podman阿里云容器镜像加速器详解

《linux配置podman阿里云容器镜像加速器详解》本文指导如何配置Podman使用阿里云容器镜像加速器:登录阿里云获取专属加速地址,修改Podman配置文件并移除https://前缀,最后拉取镜像... 目录1.下载podman2.获取阿里云个人容器镜像加速器地址3.更改podman配置文件4.使用po

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

Vue3 如何通过json配置生成查询表单

《Vue3如何通过json配置生成查询表单》本文给大家介绍Vue3如何通过json配置生成查询表单,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录功能实现背景项目代码案例功能实现背景通过vue3实现后台管理项目一定含有表格功能,通常离不开表单