Apache Storm:使不可扩展的资源可扩展

时间:2016-03-16 12:01:39

标签: java apache-storm bigdata

我最近开始向BigData世界介绍自己试验Apache Storm。我遇到了以下问题,想了很多如何解决它,但我所有的方法都显得天真。

技术

Apache Storm 0.9.3,Java 1.8.0_20

上下文

有一个大的xml文件(~400MB)需要逐行读取(xml-file-spout)。然后,每个读取文件行将被一系列螺栓发出并处理。

必须是有保证的消息处理(通过锚定发送......)

问题

就文件非常大(包含大约20亿行)而言,我使用扫描仪读取它,基于缓冲流不将整个文件加载到内存中。到现在为止还挺好。当处理过程中出现错误时会出现问题:xml-file-spout本身已经死亡,或者存在内部问题......

  1. Nimbus将重新启动喷口,但整个处理从一开始就开始;
  2. 此方法根本无法扩展。
  3. 解决方案思考

    解决第一个问题的最初想法是将当前状态保存在某处:分布式缓存,JMS队列,本地磁盘文件。当一个spout打开时,它应该找到这样的存储,读取状态并从指定的文件行继续。在这里我还考虑将状态存储在Storm的Zookeeper中,但是我不知道是否可以通过spout来解决Zookeeper(是否有这样的能力)?能否请您为此提出最佳做法?

    对于问题2我想到将初始文件分解为一组子文件并并行处理它们。它可以通过引入一个新的“破碎”喷口来完成,其中每个文件将由专用螺栓处理。在这种情况下,一个大问题提出了保证处理,导致出现错误的子文件,包含失败的行,必须完全重新处理(咒语的ack / fail方法)...你能建议最好的做法解决这个问题?

    更新

    好的,到目前为止我做了什么。

    先决条件

    以下拓扑有效,因为其所有部件(喷口和螺栓)都是幂等的。

    1. 引入了一个单独的spout,它读取文件行(逐个)并将它们发送到中间ActiveMQ队列('file-line-queue'),以便能够轻松地重放失败的文件行(请参阅下一步);

    2. 为'file-line-queue'队列创建了一个单独的spout,它接收每个文件行并将其发送到后续的bolt。至于我使用保证消息处理,如果任何螺栓失败,则重新处理消息,如果螺栓链成功,则确认相应的消息(CLIENT_ACKNOWLEDGE模式)。

    3. 如果第一个(文件读取)spout失败,则抛出RuntimeException,这会导致spout死亡。稍后,专用管理员重新启动spout,重新读取inout文件。这将导致重复的消息,但只要一切都是幂等的,它就不是问题。此外,这里值得考虑一个状态库来产生更少的重复...

      新问题

      为了使中间JMS更可靠,我添加了一个异常监听器,它为消费者和生产者恢复连接和会话。问题在于消费者:如果一个会话被恢复并且我在螺栓处理过程中没有取消JMS消息,那么在成功处理之后我需要确认它,但就会话是新的,我会收到'无法找到相关ID'问题。

      有人可以建议如何处理吗?

1 个答案:

答案 0 :(得分:1)

首先回答你的问题:

  1. 是的,您可以将状态存储在像Zookeeper这样的地方,并使用像Apache Curator这样的库来处理它。
  2. 打破文件可能会有所帮助,但仍然无法解决您必须管理状态的问题。
  3. 让我们在这里谈谈设计。 Storm是为流式传输而构建的,而非批处理。在我看来,一个更好地适用于批处理的Hadoop技术在这里可以更好地工作:MapReduce,Hive,Spark等。

    如果您打算使用storm,那么它将有助于在更容易使用的地方流式传输数据。您可以将文件写入Kafka或队列,以帮助您解决管理状态,确认/失败和重试的问题。