原理+实践,Kafka MirrorMaker使用与性能调优全解析

http://blog.csdn.net/zhanyuanlin/article/details/76695481

Kakfa MirrorMaker是Kafka 官方提供的跨数据中心的流数据同步方案。其实现原理,其实就是通过从Source Cluster消费消息然后将消息生产到Target Cluster,即普通的消息生产和消费。用户只要通过简单的consumer配置和producer配置,然后启动Mirror,就可以实现准实时的数据同步。

1. Kafka MirrorMaker基本特性

Kafka Mirror的基本特性有:

  1. 在Target Cluster没有对应的Topic的时候,Kafka MirrorMaker会自动为我们在Target Cluster上创建一个一模一样(Topic Name、分区数量、副本数量)一模一样的topic。如果Target Cluster存在相同的Topic则不进行创建,并且,MirrorMaker运行Source Cluster和Target Cluster的Topic的分区数量和副本数量不同。
  2. 同我们使用Kafka API创建KafkaConsumer一样,Kafka MirrorMaker允许我们指定多个Topic。比如,TopicA|TopicB|TopicC。在这里,|其实是正则匹配符,MirrorMaker也兼容使用逗号进行分隔。
  3. 多线程支持。MirrorMaker会在每一个线程上创建一个Consumer对象,如果性能允许,建议多创建一些线程
  4. 多进程任意横向扩展,前提是这些进程的consumerGroup相同。无论是多进程还是多线程,都是由Kafka ConsumerGroup的设计带来的任意横向扩展性,具体的分区分派,即具体的TopicPartition会分派给Group中的哪个Topic负责,是Kafka自动完成的,Consumer无需关心。 
    我们使用Kafka MirrorMaker完成远程的AWS(Source Cluster)上的Kafka信息同步到公司的计算集群(Target Cluster)。由于我们的大数据集群只有一个统一的出口IP,因此,Kafka MirrorMaker部署在本地(Target Cluster),它负责从远程的Source Cluster上的AWS Kafka 上拉取数据,然后生产到本地的Kafka。

Kafka MirrorMaker的官方文档一直没有更新,因此新版Kafka为MirrorMaker增加的一些参数、特性等在文档上往往找不到,需要看Kafka MirrorMaker的源码。Kafka MirrorMaker的主类位于kafka.tools.MirrorMaker,尤其是一些参数的解析逻辑和主要的执行流程,会比较有助于我们理解和运维Kafka MirrorMaker。


2. 新旧Consumer API的使用问题

从Kafka 0.9版本开始引入了new consumer API。相比于普通的old consumer api,new Conumser API有以下主要改变:

  • 统一了旧版本的High-Level和Low-Level Consumer API;-
  • new consumer API消除了对zookeeper的依赖,修改了ConsumerGroup的管理等等协议
  • new Consumer API完全使用Java实现,不再依赖Scala环境
  • 更好了安全认证只在new consumer中实现,在old consumer中没有。

Kakfa MirrorMaker同时提供了对新旧版本的Consumer API的支持。 
默认是旧版API,当添加–new.consumer,MirrorMaker将使用新的Consumer进行消息消费:

// Create consumers
      val mirrorMakerConsumers = if (!useNewConsumer) {//如果用户没有配置使用new consumer,则使用旧的consumer
        val customRebalanceListener = { val customRebalanceListenerClass = options.valueOf(consumerRebalanceListenerOpt) if (customRebalanceListenerClass != null) { val rebalanceListenerArgs = options.valueOf(rebalanceListenerArgsOpt) if (rebalanceListenerArgs != null) { Some(CoreUtils.createObject[ConsumerRebalanceListener](customRebalanceListenerClass, rebalanceListenerArgs)) } else { Some(CoreUtils.createObject[ConsumerRebalanceListener](customRebalanceListenerClass)) } } else { None } } if (customRebalanceListener.exists(!_.isInstanceOf[ConsumerRebalanceListener])) throw new IllegalArgumentException("The rebalance listener should be an instance of kafka.consumer.ConsumerRebalanceListener") createOldConsumers(//创建旧的consumer numStreams, options.valueOf(consumerConfigOpt), customRebalanceListener, Option(options.valueOf(whitelistOpt)), Option(options.valueOf(blacklistOpt))) } else {//用户指定使用new consumer val customRebalanceListener = { val customRebalanceListenerClass = options.valueOf(consumerRebalanceListenerOpt) if (customRebalanceListenerClass != null) { val rebalanceListenerArgs = options.valueOf(rebalanceListenerArgsOpt) if (rebalanceListenerArgs != null) { Some(CoreUtils.createObject[org.apache.kafka.clients.consumer.ConsumerRebalanceListener](customRebalanceListenerClass, rebalanceListenerArgs)) } else { Some(CoreUtils.createObject[org.apache.kafka.clients.consumer.ConsumerRebalanceListener](customRebalanceListenerClass)) } } else { None } } if (customRebalanceListener.exists(!_.isInstanceOf[org.apache.kafka.clients.consumer.ConsumerRebalanceListener])) throw new IllegalArgumentException("The rebalance listener should be an instance of" + "org.apache.kafka.clients.consumer.ConsumerRebalanceListner") createNewConsumers(//创建new consumer numStreams, options.valueOf(consumerConfigOpt), customRebalanceListener, Option(options.valueOf(whitelistOpt))) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

这是我启动Kakfa MirrorMaker 的命令:

nohup ./bin/kafka-mirror-maker.sh --new.consumer --consumer.config config/mirror-consumer.properties --num.streams 40 --producer.config config/mirror-producer.properties --whitelist 'ABTestMsg|AppColdStartMsg|BackPayMsg|WebMsg|GoldOpenMsg|BoCaiMsg' &
  • 1

mirror-consumer.properties配置文件如下:

#新版consumer摈弃了对zookeeper的依赖,使用bootstrap.servers告诉consumer kafka server的位置
bootstrap.servers=ip-188-33-33-31.eu-central-1.compute.internal:9092,ip-188-33-33-32.eu-central-1.compute.internal:9092,ip-188-33-33-33.eu-central-1.compute.internal:9092 #如果使用旧版Consumer,则使用zookeeper.connect #zookeeper.connect=ip-188-33-33-31.eu-central-1.compute.internal:2181,ip-188-33-33-32.eu-central-1.compute.internal:2181,ip-188-33-33-33.eu-central-1.compute.internal:2181 1.compute.internal:2181 #change the default 40000 to 50000 request.timeout.ms=50000 #hange default heartbeat interval from 3000 to 15000 heartbeat.interval.ms=30000 #change default session timeout from 30000 to 40000 session.timeout.ms=40000 #consumer group id group.id=africaBetMirrorGroupTest partition.assignment.strategy=org.apache.kafka.clients.consumer.RoundRobinAssignor #restrict the max poll records from 2147483647 to 200000 max.poll.records=20000 #set receive buffer from default 64kB to 512kb receive.buffer.bytes=524288 #set max amount of data per partition to override default 1048576 max.partition.fetch.bytes=5248576 #consumer timeout #consumer.timeout.ms=5000
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

mirror-producer.properties的配置文件如下:

bootstrap.servers=10.120.241.146:9092,10.120.241.82:9092,10.120.241.110:9092 # name of the partitioner class for partitioning events; default partition spreads data randomly #partitioner.class= # specifies whether the messages are sent asynchronously (async) or synchronously (sync) producer.type=sync # specify the compression codec for all data generated: none, gzip, snappy, lz4. # the old config values work as well: 0, 1, 2, 3 for none, gzip, snappy, lz4, respectively compression.codec=none # message encoder serializer.class=kafka.serializer.DefaultEncoder
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

同时,我使用kafka-consumer-groups.sh循环监控消费延迟:

bin/kafka-consumer-groups.sh  --bootstrap-server ip-188-33-33-31.eu-central-1.compute.internal:9092,ip-188-33-33-32.eu-central-1.compute.internal:9092,ip-188-33-33-33.eu-central-1.compute.internal:9092 --describe --group africaBetMirrorGroupTest --new-consumer
  • 1

当我们使用new KafkaConsumer进行消息消费,要想通过kafka-consumer-groups.sh获取整个group的offset、lag延迟信息,也必须加上–new-consumer,告知kafka-consumer-groups.sh,这个group的消费者使用的是new kafka consumer,即group中所有consumer的信息保存在了Kafka上的一个名字叫做__consumer_offsets的特殊topic上,而不是保存在zookeeper上。我在使用kafka-consumer-groups.sh的时候就不知道还需要添加–new-consumer,结果我启动了MirrorMaker以后,感觉消息在消费,但是就是在zookeeper的/consumer/ids/上找不到group的任何信息。后来在stack overflow上问了别人才知道。

3. 负载不均衡原因诊断以及问题解决

在我的另外一篇博客《Kafka为Consumer分派分区:RangeAssignor和RoundRobinAssignor》中,介绍了Kafka内置的分区分派策略:RangeAssignor和RoundRobinAssignor。由于RangeAssignor是早期版本的Kafka的唯一的分区分派策略,因此,默认不配置的情况下,Kafka使用RangeAssignor进行分区分派,但是,在MirrorMaker的使用场景下,RoundRobinAssignor更有利于均匀的分区分派。甚至在KAFKA-3831中有人建议直接将MirrorMaker的默认分区分派策略改为RoundRobinAssignor。那么,它们到底有什么区别呢?我们先来看两种策略下的分区分派结果。在我的实验场景下,有6个topic:ABTestMsg|AppColdStartMsg|BackPayMsg|WebMsg|GoldOpenMsg|BoCaiMsg,每个topic有两个分区。由于MirrorMaker所在的服务器性能良好,我设置--num.streams 40,即单台MirrorMaker会用40个线程,创建40个独立的Consumer进行消息消费,两个MirrorMaker加起来80个线程,80个并行Consumer。由于总共只有6 * 2=12个TopicPartition,因此最多也只有12个Consumer会被分派到分区,其余Consumer空闲。 
我们来看基于RangeAssignor分派策略的kafka-consumer-groups.sh 的结果:

TOPIC                          PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG        CONSUMER-ID HOST CLIENT-ID ABTestMsg 0 780000 820038 49938 africaBetMirrorGroupTest-4-cf330e66-1319-4925-9605-46545df13453/114.113.198.126 africaBetMirrorGroupTest-0 ABTestMsg 1 774988 820038 55000 africaBetMirrorGroupTest-19-c77523e7-7b87-472b-9a26-cd902888944d/114.113.198.126 africaBetMirrorGroupTest-1 AppColdStartMsg 0 774000 820039 55938 africaBetMirrorGroupTest-19-674d8ad4-39d2-40cc-ae97-f4be9c1bb154/114.113.198.126 africaBetMirrorGroupTest-0 AppColdStartMsg 1 774100 820045 56038 africaBetMirrorGroupTest-15-91c67bf8-0c1c-42ac-97f0-5369794c2d1b/114.113.198.126 africaBetMirrorGroupTest-1 BackPayMsg 0 780000 820038 49938 africaBetMirrorGroupTest-4-cf330e66-1319-4925-9605-46545df13453/114.113.198.126 africaBetMirrorGroupTest-0 BackPayMsg 1 774988 820038 55000 africaBetMirrorGroupTest-19-c77523e7-7b87-472b-9a26-cd902888944d/114.113.198.126 africaBetMirrorGroupTest-1 WebMsg 0 774000 820039 55938 africaBetMirrorGroupTest-19-674d8ad4-39d2-40cc-ae97-f4be9c1bb154/114.113.198.126 africaBetMirrorGroupTest-0 WebMsg 1 774100 820045 56038 africaBetMirrorGroupTest-15-91c67bf8-0c1c-42ac-97f0-5369794c2d1b/114.113.198.126 africaBetMirrorGroupTest-1 GoldOpenMsg 0 780000 820038 49938 africaBetMirrorGroupTest-4-cf330e66-1319-4925-9605-46545df13453/114.113.198.126 africaBetMirrorGroupTest-0 GoldOpenMsg 1 774988 820038 55000 africaBetMirrorGroupTest-19-c77523e7-7b87-472b-9a26-cd902888944d/114.113.198.126 africaBetMirrorGroupTest-1 BoCaiMsg 0 774000 820039 55938 africaBetMirrorGroupTest-19-674d8ad4-39d2-40cc-ae97-f4be9c1bb154/114.113.198.126 africaBetMirrorGroupTest-0 BoCaiMsg 1 774100 820045 56038 africaBetMirrorGroupTest-15-91c67bf8-0c1c-42ac-97f0-5369794c2d1b/114.113.198.126 africaBetMirrorGroupTest-1 - - - - - africaBetMirrorGroupTest-

转载于:https://www.cnblogs.com/davidwang456/articles/8360067.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值