Apache Storm加入模式 - 至少一次

时间:2015-11-02 12:27:58

标签: rabbitmq apache-storm

我在Storm中实现了一个从RabbitMQ spout(https://github.com/ppat/storm-rabbitmq)接收消息的螺栓。

我必须在Storm中处理的每个事件都是来自Rabbit的两条消息,所以我在bolt上有一个fieldsGrouping,这样两条消息就会在同一个螺栓中到达。

我的第一个方法是:

  1. 接收第一个元组并将消息保存在内存
  2. Ack the first tuple
  3. 当第二个元组到达时,从内存中取出第一个,并从喷口发出一个新的元组锚定到第二个。
  4. 这样可行,但如果一名工人死亡,我可能会丢失消息,因为我会在获得第二个元组之前获取第一个元组并进行处理。

    我将其更改为:

    1. 接收第一个元组并将其保存在内存中
    2. 当第二个元组到达时从内存中获取第一个元组时,发出一个新的元组,它固定在两个输入元组上并确认两个输入元组。
    3. 内存缓存是一个时间到期的Guava缓存,当一个元组由于超时而被驱逐时,我将在拓扑中失败(),以便后者重新处理。

      这似乎有效,但是当我做了一些测试时,我遇到了系统停止从Rabbit Queue获取消息的情况。

      队列上的预取设置为5,并且setMaxSpoutPending为7的spout。在Rabbit界面中,我看到5个未分组的消息。

      在风暴日志中,我看到同样的元组一遍又一遍地从缓存中逐出。

      据我所知,问题是spout只会获取5条消息,这些消息都是一对的第一部分。我可以增加预取,但这并不保证在生产中不会发生这种情况。

      所以我的问题是:如何在Storm中处理这些问题时实现连接?

1 个答案:

答案 0 :(得分:1)

Storm无法为此提供良好的解决方案......您需要的是一个缓冲第一个元组的可靠存储(即有状态运算符)。因此,您可以立即确认第一个元组,并在失败后恢复状态。

  1. 据我所知, Trident 支持一些状态处理。但我从未使用它。
  2. 作为第二种选择,您可以使用分布式键值存储(如Casandra)作为缓冲区。当然,这将是一个手写的解决方案,即您需要自己编写所有Casandra交互的代码。
  3. 最后但并非最不重要的是,您可以切换到支持Apache Flink等有状态运算符的流处理系统。 (免责声明:我是Flink的提交者)