理论教育 Scala语言实战:NoReceiver方法的消息消费者设计

Scala语言实战:NoReceiver方法的消息消费者设计

时间:2023-11-24 理论教育 版权反馈
【摘要】:与基于Receiver实现的方法相比,这种基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法,能周期性地查询Apache Kafka中每个Topic分区的最新offset偏移量,并能据此定义每个批处理中的偏移范围。Exactly-once semantics:也称为准确一次性语义,在基于Receiver实现的Apache Kafka和Apache Spark Streaming整合方法中,是使用Kafka高级API来实现这种方法的,然而Consumer的offset被存储在Zookeeper中。这主要是Apache Spark Streaming接收真实的数据和Zookeeper跟踪offset不一致性造成的。

Scala语言实战:NoReceiver方法的消息消费者设计

在Apache Kafka与Apache Spark Streaming整合中,为了能确保更强的端到端映射关系,在Apache Spark 1.3版本中,实现了基于No Receiver的Apache Kafka与Apache Spark Stream⁃ing整合方法,这种方法在开发Apache Spark Streaming实时流应用程序时,核心类入口也是Apache Spark Streaming实现的KafkaUtils类,之后通过KafkaUtils中的createStream()方法来获取Apache Kafka的Brokers消息数据,之后形成Apache Spark Streaming的输入流。在cre⁃ateStream()方法中,会调用另外一个核心类DirectKafkaInputDStream,这个类是基于No Re⁃ceiver实现的精髓,DirectKafkaInputDStream类是使用Apache Kafka的Low Level Consumer(Simple Consumer)API实现的。

与基于Receiver实现的方法相比,这种基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法,能周期性地查询Apache Kafka中每个Topic分区的最新offset偏移量,并能据此定义每个批处理中的偏移范围。当Apache Spark Streaming启动任务来处理数据的时候,使用Apache Kafka低级Consumer API来读取Kafka上面的偏移范围,就像在文件系统中读取文件一样简单方便。基于No Receiver实现Apache Kafka与Apache Spark Streaming整合方法在Apache Spark 1.3版本中提供了Scala API和Java API,在Apache Spark 1.4版本中提供了Python API。

与基于Receiver实现的Apache Kafka和Apache Spark Streaming整合方法相比较,基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法有如下优点:

简化并行:基于No Receiver方法已经不需要创建多个input Kafka,之后再将这多个input Kafka进行union操作。直接通过directStream,Apache Spark Streaming可以创建和A⁃pache Kafka Consumer分区数量一样多的RDD分区数量。这样Apache Spark Streaming就能并行地读取Kafka上的数据,这就实现了Kafka分区和RDD分区一一对应的关系,这种方式也变得非常容易理解和调整。

更高的效率:为了达到零数据丢失,基于Receiver实现的Apache Kafka和Apache Spark Streaming整合方法引入了WAL(Write Ahead Log)功能,这实际上是一种非常低效的方法,因为数据流过的时候,数据要保存两次,一次保存到Kafka中,一次通过WAL功能保存到某个文件系统(比如HDFS)中。但是基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法,通过不使用Receiver来消除了这个问题,从而变得更加高效,因为不需要再写日志到某个文件系统。消除这个问题的根本原因在于,Apache Spark Streaming能使用Apache Kafka低级消费API来读取Kafka上面的偏移范围,而不是通过Zookeeper来获取。因此,只要Kafka上的数据存在,消息数据就能从Kafka上进行恢复。

Exactly-once semantics:也称为准确一次性语义,在基于Receiver实现的Apache Kafka和Apache Spark Streaming整合方法中,是使用Kafka高级API来实现这种方法的,然而Consumer的offset被存储在Zookeeper中。这是Kafka非常经典的消费数据的模式,这个模式必须的使用WAL(Write Ahead Log)功能,才能确保零数据丢失。但是这种方式还是会出现在一些任务失败时,一些记录会被消费两次。这主要是Apache Spark Streaming接收真实的数据和Zookeeper跟踪offset不一致性造成的。因此,基于No Receiver来实现Apache Kaf⁃ka与Apache Spark Streaming整合方法,使用的是Apache Kafka低级Consumer API来实现,并不在使用Zookeeper来跟踪Consumer offset,而是直接基于checkpoints通过Apache Spark Streaming来追踪offset,这样就消除了Apache Streaming和Zookeeper/Kafka的不一致性。因此,即使任务运行失败,每条记录都能被Apache Spark Streaming高效准确一次性地被接收。为了在输出结果获得准确一次性语义,在数据输出操作中,保持数据到另外的数据存储系统中必须是幂等的,或者以原子事务的方式保存数据的结果和数据偏移量。

基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法优点很多,但是不能通过Zookeeper来更新offset,因此基于Zookeeper的Kafka监控工具将失去了作用。然而,你自己可以用基于No Receiver方法来获取offset,并自己来更新Zookeeper中的offset。

上面对基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法进行了总结分析,现在我们就使用这种方法也来实现单词计数的Apache Spark Streaming应用程序。参考代码如下:

该应用程序创建了一个DirectKafkaWordCount类,代码进行了详细注释,其中的代码已经在Apache Spark的发布包中,读者只需要搭建好Apache Spark的集群环境,运行如下命令,就可以了查看Apache Spark Streaming的实时流统计展现效果,即对单词的个数进行统计。参考命令如下。(www.daowen.com)

这里对上面命令参数的含义稍微进行说明:

参数一:broker1-host:port,broker2-host:port,实际上就是Apache Kafka集群服

务器,也称为Broker,这里只服务器的名称加端口号,多个服务器之间用逗号隔开。

参数二:topic1,topic2,Apache Kafka的Topics,可以是一个,也可以多个,多个之

间用英文逗号隔开。

这里基于No Receiver实现了Apache Kafka与Apache Spark Streaming整合方法,实现了实时流单词统计,如果读者想更加深入了解基于No Receiver实现的Apache Kafka和Apache Spark Streaming整合方法,也可以详细阅读Apache Spark Streaming中的DirectKafkaInputD⁃Stream类的源码

通过上面对基于Receiver来实现Apache Kafka与Apache Spark Streaming整合方法和基于No Receiver来实现Apache Kafka与Apache Spark Streaming整合方法分别实现了单词统计的应用程序,通过这两个方法比较发现,基于Apache Spark Streaming自带的整合Kafka的方法来开发实际需求的实时流处理应用变得非常简单,用户不需要再实现Apache Kafka数据流到Apache Spark RDDs的细节过程,开发中只需要调用KafkaUtils.createStream()方法,就可以实现想要的功能需求,从这一点也说明Spark的强大和简洁,当然,读者对底层的实现原理比较了解和熟悉的话,在排除问题、设计更优的业务实现方案、性能调优时会有很大的帮助。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈