使用RabbitMQ源

时间:2018-06-04 16:05:53

标签: java apache-spark rabbitmq spark-structured-streaming

我正在尝试编写Structured Streaming的自定义接收器,该接收器将使用来自RabbitMQ的消息。 Spark recently released DataSource V2 API,看起来很有前途。由于它抽象了许多细节,我想在简单性和性能方面使用这个API。但是,由于它很新,因此可用的资源不多。我需要经验丰富的Spark人澄清,因为他们会更容易掌握关键点。我们走了:

我的出发点是博客文章系列,第一部分是here。它显示了如何在没有流功能的情况下实现数据源。为了制作流媒体源,我稍微改变了它们,因为我需要实现MicroBatchReadSupport而不是(或除了)DataSourceV2

为了提高效率,让多个spark执行器同时消耗RabbitMQ,即来自同一队列是明智的。如果我没有感到困惑,输入-in Spark的术语的每个分区都对应于队列-in RabbitMQ术语中的消费者。因此,我们需要为输入流设置多个分区,对吧?

part 4 of the series类似,我按如下方式实施MicroBatchReader

@Override
public List<DataReaderFactory<Row>> createDataReaderFactories() {
    int partition = options.getInt(RMQ.PARTITICN, 5);
    List<DataReaderFactory<Row>> factories = new LinkedList<>();
    for (int i = 0; i < partition; i++) {
        factories.add(new RMQDataReaderFactory(options));
    }
    return factories;
}

我正在返回一个工厂列表,并希望列表中的每个实例都将用于创建一个读者,这也是一个消费者。这种做法是否正确?

我希望我的收件人可靠,即在每次处理完邮件后(或者至少写入chekpoint目录进行进一步处理),我需要回复RabbitMQ。问题从这里开始:这些工厂是在驱动程序中创建的,实际的读取过程是通过DataReader s在执行程序中进行的。但是,commit方法是MicroBatchReader的一部分,而不是DataReader。由于每DataReaderMicroBatchReaderRabbitMQ,我应该如何将这些消息发回DataReader?或者我应该在commit上调用next方法时遇到问题?安全吗?如果是这样,那么DataReaderFactory函数的目的是什么?

澄清: OBFUSCATION:答案中提供的关于重命名某些类/函数的链接(除了那里的解释)使一切 更加清晰 比以往更糟糕。引自there

  

重命名:

     
      
  • InputPartitionDataReader

  •   
  • InputPartitionReaderInputPartition

  •   
     

...

     

InputPartitionReader的目的是管理网站的生命周期   相关的阅读器,现在称为DataReaderFactory,带有   显式创建操作以镜像关闭操作。这不是   从API更长时间清除,因为set define off; spool install_scripts_logs.log; Prompt plsql_file_1.sql @current_folder_location/plsql_file_1.sql show errors; Prompt plsql_file_2.sql @current_folder_location/plsql_file_2.sql show errors; Prompt plsql_file_1.sql @current_folder_location/plsql_file_2.sql show errors; spool off; 似乎更多   它是通用的,并且它不清楚为什么要生成它们的一组   阅读。

编辑:但是,docs清楚地说&#34;阅读器工厂将被序列化并发送给执行者,然后数据阅读器将在执行者身上创建并执行实际阅读。&#34;

为了使消费者可靠,我必须在Spark方面提交之后才确认特定消息。 Note that消息必须在通过它传递的同一连接上进行确认,但在驱动程序节点调用commit函数。我如何在worker / executor节点上提交?

1 个答案:

答案 0 :(得分:0)

<德尔> &GT;我将返回一个工厂列表,并希望列表中的每个实例都将用于创建一个读者,这也将是一个消费者。这种做法是否正确? 源[socket] [1]源实现有一个线程将消息推送到内部ListBuffer。换句话说,有一个消费者(线程)填充内部ListBuffer,然后**由`planInputPartitions`(`createDataReaderFactories`得到[重命名] [2]到`planInputPartitions`)划分为分区。 另外,根据[MicroBatchReadSupport]的Javadoc [3] &GT;执行引擎将在流式查询开始时创建一个微批处理读取器,为每个要处理的批处理调用setOffsetRange和createDataReaderFactories,然后在执行完成时调用stop()。请注意,由于重新启动或故障恢复,单个查询可能会有多次执行。 换句话说,`createDataReaderFactories`应该被调用**多次**,据我的理解,这表明每个`DataReader`都负责一个静态输入分区,这意味着DataReader不应该是一个消费者。 ---------- &GT;但是,commit方法是MicroBatchReader的一部分,而不是DataReader ...如果是这样,那么commit函数的目的是什么呢? 也许提交函数的部分原理是防止MicroBatchReader的内部缓冲区变大。通过提交Offset,您可以有效地从缓冲区中删除小于Offset的元素,因为您承诺不再处理它们。您可以使用`batches.trimStart(offsetDiff)`在套接字源代码中看到这种情况 <德尔> 我不确定是否实现了一个可靠的接收器,所以我希望有一个更有经验的Spark人来找我并且抓住你的问题,因为我也很感兴趣! 希望这可以帮助!

修改

我只研究了socketwiki-edit来源。这些来源不是生产准备好的,这是问题所不能找到的。相反,kafka来源是一个更好的起点,与前面提到的来源不同,像作者一样正在寻找多个消费者。

然而,也许如果您正在寻找不可靠的来源,上面的socket和wikiedit源提供了一个不那么复杂的解决方案。