spark-streaming-kafka-0-10:如何限制Spark分区的数量

时间:2017-02-20 17:54:29

标签: scala apache-spark apache-kafka spark-streaming kafka-consumer-api

是否可以使用 spark-streaming-kafka-0-10 库配置Spark,以使用单个任务读取多个Kafka分区或整个Kafka主题,而不是为其创建不同的Spark任务每个Kafka分区都可用吗?

请原谅我对这些技术的粗略理解;我想我仍然是Spark和Kafka的新手。架构和设置大多只是乱七八糟地探索和了解这些技术如何协同工作。

我有四个虚拟主机,一个带有Spark主机,每个主机都有一个Spark工作器。其中一个主机也运行基于Spotify's Docker image的Kafka代理。每个主机有四个内核和大约8 GB的未使用RAM。

Kafka经纪人有206个主题,每个主题有10个分区。因此,共有2,060个分区供应用程序读取。

我正在使用spark-streaming-kafka-0-10库(目前是实验性的)从Spark Streaming作业订阅Kafka中的主题。我正在使用SubscribePattern类来订阅Spark中的所有206个主题:

val stream = KafkaUtils.createDirectStream[String, String](
  ssc,
  PreferConsistent,
  SubscribePattern[String, String](Pattern.compile("(pid\\.)\\d+"),
  kafkaParams)
)

当我将此作业提交给Spark主服务器时,看起来启动了16个执行程序,一个用于集群中的每个核心。看起来每个Kafka分区都有自己的任务,共计2,060个任务。我认为我的16个遗嘱执行人员群体在完成这么多任务时遇到了麻烦,因为工作在1500到1800个任务完成之间的不同点上都会失败。

我发现a tutorial by Michael Noll from 2014使用 spark-streaming-kafka-0-8 库来控制每个主题的使用者线程数:

val kafkaParams: Map[String, String] = Map("group.id" -> "terran", ...)

val consumerThreadsPerInputDstream = 3
val topics = Map("zerg.hydra" -> consumerThreadsPerInputDstream)
val stream = KafkaUtils.createStream(ssc, kafkaParams, topics, ...)

2 个答案:

答案 0 :(得分:3)

  

是否可以使用spark-streaming-kafka-0-10库配置Spark以使用单个任务读取多个Kafka分区或整个Kafka主题,而不是为每个可用的Kafka分区创建不同的Spark任务?

您可以通过调用流上的repartition来更改生成的分区数,但之后会丢失Kafka和RDD分区之间的1:1对应关系。

Kafka分区生成的任务数与您拥有16个执行程序的事实无关。执行程序的数量取决于您的设置和您正在使用的资源管理器。

Kafka分区与带有直接流API的RDD分区之间存在1:1映射,每个执行器将从Kafka中获取这些分区的子集,并处理每个分区是独立的并且可以在其上计算的#39自己的。这与基于接收器的API不同,后者在任意执行器上创建单个接收器,并通过节点上的线程消耗数据本身。

如果你有206个主题和10个分区,你最好有一个合适大小的集群,它可以处理生成的任务的负载。您可以控制每个分区生成的最大消息,但您可以更改分区数,除非您将调用repartition转换的重排效果。

答案 1 :(得分:1)

第二种方法将最符合您的要求。只需要设置consumerThreadsPerInputDstream = 1.因此每次读取操作只会创建一个线程,因此每个集群将涉及一台机器。