确保为特定队列扩展不超过 N 个实例
Posted
技术标签:
【中文标题】确保为特定队列扩展不超过 N 个实例【英文标题】:ensuring no more than N instances are scaled out for a specific queue 【发布时间】:2019-11-19 04:25:29 【问题描述】:我的功能是将有效负载发送到不同的 sftp 服务器。这些服务器可以接受的连接数是有限的。
我需要一个解决方案来限制我们与这些服务器的连接。
该功能由存储队列触发,设计初稿为:
然后我了解到每个函数只能有 1 个触发器,这导致我对另一个聚合队列进行了沙化:
我可以在原始队列上设置batchSize/newBatchThreshold,但我不确定这是否可行,因为原始队列不会知道何时将消息推送到聚合队列。
-
我需要该函数不要将队列 X 中的所有消息扩展到超过 N 个实例,因为 sftp 服务器 X 不会接受超过 N 个连接。
此外,对于来自队列 Y 的所有消息,我需要将函数横向扩展至不超过 M 个实例,因为 sftp 服务器 Y 不会接受超过 M 个连接。
上述场景的实例总数为 M + N。
我们如何调整我们的设计以适应这些要求?
【问题讨论】:
【参考方案1】:对此没有 100% 防弹的解决方案,该问题已被跟踪 here。
最好的方法是在由聚合队列触发的函数应用程序的应用程序设置中将WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
设置为1
。然后,您应该只获得一个 Function App 的并发实例,因此 batchSize
设置实际上对速率限制很有用。
在这种情况下,您不需要限制队列处理器 X/Y/Z,让消息流向聚合。
现在,我不明白是否只有来自队列 X 的消息会触及 SFPT X,或者它是多对多的。如果是一对一的,那么去掉聚合队列,拥有三个Function并分别限制每个队列的并发是有意义的。
反正限制设置是我上面建议的。
如果这仍然不能满足您的要求,您可以切换到其他消息服务。例如,将一种类型的所有消息发送到 Service Bus 的单独会话或 Event Hub 的单个分区中,这自然会限制代理级别的并发。
【讨论】:
非常感谢!不幸的是,我不能接受你的建议have three Functions and limit the concurrency for each of the queues separately.
,因为我可能有 100 个队列针对 100 个不同的目的地
好吧,也许它很难管理,但它也适用于 100 个 :) 如果你将所有 100 个合并到一个聚合中,我认为你无法限制所有这些以匹配每个目的地的确切限制。相反,您必须设置非常保守的值并让异常值重试。
所以您的建议是创建 100 个队列,包含 100 个功能应用程序,将每个功能应用程序的 WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT 设置为 1,对吧/?
我在想也许这是一个持久功能问题?对此有何其他指导?我非常坚持要做什么,我阅读了您的数十篇文章和数百篇其他文章,并且真的想不出适合架构的解决方案,我愿意接受任何建议,也许在这种情况下,活动中心会有所帮助?但不确定
100 个队列是可能的,但听起来很复杂。耐用可能是一种方法,尽管我必须考虑确切的方法。这些队列每秒处理多少条消息?我建议的服务总线或事件中心怎么样?【参考方案2】:
选项 1:取决于 sftp 的错误响应
sftp 服务器是否返回 429(请求过多)响应?或者类似的东西?当你得到这样的响应时,你可以直接退出函数而不从队列中删除消息。消息将在 30 秒后再次可见,并会触发一个函数。 30 秒是 visibilitytimeout
的默认值,并且是 customizable on 每个消息的基础。
选项 2:分布式锁
我不知道带有计数器的分布式锁定解决方案。另一种方法是使用 SQL 数据库和原子事务自行实施锁定解决方案。处理来自队列 X 的消息时的函数将查看数据库以查看 X 的锁定计数器是否小于 N,如果是则将其增加 1,然后处理该消息。在这种情况下,即使您的函数崩溃,您也必须确保锁被释放。即,实现具有租约到期时间的锁。
【讨论】:
以上是关于确保为特定队列扩展不超过 N 个实例的主要内容,如果未能解决你的问题,请参考以下文章