流应用中的瓶颈导致消息丢失

时间:2019-04-29 18:27:20

标签: spring-cloud-stream spring-cloud-dataflow

  • 用于Cloud Foundry v1.4.x的Spring Cloud Data Flow(SCDF)服务器
  • 为消息传输配置的RabbitMQ服务磁贴

已部署的Spring Cloud数据流流具有一个处理器,该处理器可以比下游处理器或接收器处理传入消息的速度更快地生成传出消息。这会导致RabbitMQ传输出现瓶颈,最终导致消息丢失。

在我们的私有云环境中,我们的Rabbit服务磁贴具有默认设置max-length=1000max-length-bytes=1000000。我们目前无法修改这些设置以增加这两种功能。

我们尝试在消费应用程序上设置prefetch的值(我相信设置为deployer.<appname>.rabbit.bindings.consumer.prefetch=10000),这似乎实际上提高了消费应用程序在较短的时间内消费更多消息的能力。时间,但这仅在有限的情况下有效。如果流中有大量数据,我们仍然很可能会遇到消息丢失的限制。在上面的示例中,我们似乎通过设置预取将消费应用程序的容量从1000增加到11000。

我们还尝试使用自动扩展服务,因此我们可以增加使用应用程序的活动实例的数量,这也可以明显增加其容量。但是,这似乎也像通过创可贴解决问题,而不是使用本质上能够以弹性方式处理潜在交易量预期的基础结构和/或服务。如果我们不知道一天中的特定时间什么时候卷将显着增加,该怎么办?如果卷以某种速率增长,以致于自动缩放器设置中的CPU阈值无法足够快地跟上活动实例,那么该怎么办呢?丢失的消息?

  • 我们尚未尝试设置RabbitMQ服务来保证交付。根据文档,似乎更容易分辨出何时未传递消息,而不是确定传递。我们不知道这是否是一个可行的选择,因此正在寻求建议。
  • 我们尚未尝试在流应用本身中实施任何限制。我们不知道这是否是一个可行的选择,因此正在寻求建议。
  • 我们没有尝试将应用程序绑定到DLQ或重新排队处理失败的消息。我们不知道这是否是一个可行的选择,因此正在寻求建议。
  • 我们尚未尝试将SCDF服务器绑定到Cloud Foundry服务磁贴外部的我们自己的Rabbit服务实例。从理论上讲,这将是RabbitMQ实例,我们可以更好地控制队列深度和字节大小限制,在这里我们可以将它们设置为更轻松地处理预期的负载。
  • 我们还没有尝试过像Kafka这样的替代运输机制。我们不知道这是否是一个可行的选择,因此正在寻求建议。

我很难相信其他人在这些流传输范例中没有遇到过类似性质的问题,并且我很好奇是否存在公认的最佳实践解决方案,或者我们是否需要仔细研究在这些情况下是否会误用流式传输模式。

我们的基本要求是,在任何流应用程序上下文中丢失消息都是不可接受的情况,我们需要确定一种最佳的方式来配置环境,或者分析我们的实现选择以确保我们的实现在繁重的情况下稳健可靠加载。

对此有任何社区或重要人士的建议吗?

1 个答案:

答案 0 :(得分:2)

警告

感谢您提供了这么多的细节,问题以及您对Spring Cloud Stream和SCDF的兴趣,但是我希望您理解这对SO来说并不是真正的问题,因为它具有太多的变量,因此不可能答案,更适合进行某种类型的讨论。也许是GitHub中提到的两个项目的功能请求,我们可以在那里讨论。 无论如何,我会尽力确保它不会被解答。

您要问的是背压,这确实是一个非常有效的问题。但是,需要理解的是,Spring Cloud Stream和随后的SCDF选择了支持多个消息传递系统/协议(通过活页夹)以将微服务连接在一起,而不是创建我们自己的微服务。并不是每个消息传递系统/协议都支持背压,而确实提供了不同的机制来实现背压,因此很难/不可能在框架级别上提供某种通用抽象。

因此,有效的讨论变成了架构/设计的讨论,我将很高兴参与其中,但需要更多的上下文。 例如,在RabbitMQ的上下文中,一种方式可能是生产者轮询队列大小(RabbitAdmin.queueProperties(queue)),并在超过某个阈值时停止发布。但是正如我所说,做事还有更多的技巧和方法,我们肯定需要更多的上下文。

我还应该提到,我们正在研究RSocket绑定程序,它是一种本机支持背压的系统和协议。

我希望这会有所帮助。 。