确保为特定队列扩展不超过 N 个实例
ensuring no more than N instances are scaled out for a specific queue
我的功能是将负载发送到不同的 sftp 服务器。这些服务器在它们可以接受的连接数量上受到限制。
我需要一个解决方案来限制我们与这些服务器的连接。
函数由存储队列触发,设计初稿为:
然后我了解到每个函数只能有 1 个触发器,这让我想到了另一个聚合队列:
我可以在原始队列上设置 batchSize/newBatchThreshold,但我不确定这是否有效,因为原始队列不知道何时将消息推送到 聚合队列.
- 我需要的功能是不为来自队列 X 的所有消息扩展到超过 N 个实例,因为 sftp 服务器 X 不会接受超过 N 个连接。
- 此外,我需要该功能将来自队列 Y 的所有消息扩展到不超过 M 个实例,因为 sftp 服务器 Y 不会接受超过 M 个连接。
上述情况的实例总数为 M + N。
我们如何调整设计以满足这些要求?
没有 100% bullet-proof 的解决方案,已跟踪问题 here。
最好的办法是在聚合队列触发的Function App的应用程序设置中将WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
设置为1
。然后,您应该只获得一个 Function App 的并发实例,因此 batchSize
设置实际上对速率限制很有用。
在这种情况下,您不需要限制队列处理器X/Y/Z,让消息流向聚合。
现在,我不明白是只有来自队列 X 的消息接触 SFPT X,还是 many-to-many。如果是 one-on-one,那么去掉聚合队列,拥有三个 Function 并分别限制每个队列的并发是有意义的。
无论如何,限制设置是我上面建议的。
如果仍然不能满足您的要求,您可以切换到其他消息服务。例如,将一种类型的所有消息发送到 Service Bus 的单独会话或 Event Hub 的单个分区,这自然会限制代理级别的并发。
选项1:取决于sftp的错误响应
sftp 服务器 return 是否有 429(请求过多)响应?或者类似的东西?当您收到这样的响应时,您可以直接退出该函数,而无需从队列中删除消息。消息会在 30 秒后再次变为可见,并会触发一个函数。 30 秒是 visibilitytimeout
的默认值,是 customizable on per-msg 的基础。
方案二:分布式锁
我完全不知道带计数器的分布式锁定解决方案。另一种方法是使用 SQL 数据库和原子事务自行实现锁定解决方案。处理来自队列 X 的消息时的函数将查看数据库以查看 X 的锁定计数器是否小于 N,如果是则将其增加 1,然后处理消息。在这种情况下,您必须确保即使您的函数崩溃也能释放锁。即实现带租约到期时间的锁。
我的功能是将负载发送到不同的 sftp 服务器。这些服务器在它们可以接受的连接数量上受到限制。
我需要一个解决方案来限制我们与这些服务器的连接。
函数由存储队列触发,设计初稿为:
然后我了解到每个函数只能有 1 个触发器,这让我想到了另一个聚合队列:
我可以在原始队列上设置 batchSize/newBatchThreshold,但我不确定这是否有效,因为原始队列不知道何时将消息推送到 聚合队列.
- 我需要的功能是不为来自队列 X 的所有消息扩展到超过 N 个实例,因为 sftp 服务器 X 不会接受超过 N 个连接。
- 此外,我需要该功能将来自队列 Y 的所有消息扩展到不超过 M 个实例,因为 sftp 服务器 Y 不会接受超过 M 个连接。
上述情况的实例总数为 M + N。
我们如何调整设计以满足这些要求?
没有 100% bullet-proof 的解决方案,已跟踪问题 here。
最好的办法是在聚合队列触发的Function App的应用程序设置中将WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT
设置为1
。然后,您应该只获得一个 Function App 的并发实例,因此 batchSize
设置实际上对速率限制很有用。
在这种情况下,您不需要限制队列处理器X/Y/Z,让消息流向聚合。
现在,我不明白是只有来自队列 X 的消息接触 SFPT X,还是 many-to-many。如果是 one-on-one,那么去掉聚合队列,拥有三个 Function 并分别限制每个队列的并发是有意义的。
无论如何,限制设置是我上面建议的。
如果仍然不能满足您的要求,您可以切换到其他消息服务。例如,将一种类型的所有消息发送到 Service Bus 的单独会话或 Event Hub 的单个分区,这自然会限制代理级别的并发。
选项1:取决于sftp的错误响应
sftp 服务器 return 是否有 429(请求过多)响应?或者类似的东西?当您收到这样的响应时,您可以直接退出该函数,而无需从队列中删除消息。消息会在 30 秒后再次变为可见,并会触发一个函数。 30 秒是 visibilitytimeout
的默认值,是 customizable on per-msg 的基础。
方案二:分布式锁
我完全不知道带计数器的分布式锁定解决方案。另一种方法是使用 SQL 数据库和原子事务自行实现锁定解决方案。处理来自队列 X 的消息时的函数将查看数据库以查看 X 的锁定计数器是否小于 N,如果是则将其增加 1,然后处理消息。在这种情况下,您必须确保即使您的函数崩溃也能释放锁。即实现带租约到期时间的锁。