Ruby on rails 延迟工作:每个租户一次一个工作?

Ruby on rails 延迟工作:每个租户一次一个工作?,ruby-on-rails,scope,multi-tenant,delayed-job,Ruby On Rails,Scope,Multi Tenant,Delayed Job,我有一个多租户Rails应用程序,有多个延迟工作人员 为了避免租户特定的工作重叠,我希望将工人彼此分开,这样每个工人一次只处理一个租户特定的任务 我考虑使用(命名)队列列,并添加“租户1”、“租户2”等等。不幸的是,队列必须在配置期间命名,因此这一原则对于许多租户来说不够灵活 有没有一种方法可以自定义作业选择下一个任务的方式?是否有其他方法来定义范围?您最好的选择可能是旋转一个实现分布式锁的自定义解决方案-基本上,所有工作人员都正常运行并从通常的队列中拉出,但在使用另一个系统(Redis、RDB

我有一个多租户Rails应用程序,有多个延迟工作人员

为了避免租户特定的工作重叠,我希望将工人彼此分开,这样每个工人一次只处理一个租户特定的任务

我考虑使用(命名)队列列,并添加“租户1”、“租户2”等等。不幸的是,队列必须在配置期间命名,因此这一原则对于许多租户来说不够灵活


有没有一种方法可以自定义作业选择下一个任务的方式?是否有其他方法来定义范围?

您最好的选择可能是旋转一个实现分布式锁的自定义解决方案-基本上,所有工作人员都正常运行并从通常的队列中拉出,但在使用另一个系统(Redis、RDBMS、API等)执行工作检查之前验证没有其他工作人员正在为该租户执行作业。如果未处理该租户,则为相关租户设置锁并处理作业。如果租户被锁定,则不要执行该工作。这是你在许多实现细节上的调用,比如是否继续尝试另一个作业,重新排队队列中的作业,是否考虑失败,并将其绑定到重试限制,或者完全做其他事情。这是非常开放的,所以我将把细节留给您,但这里有一些提示:

  • 遗产将是你的朋友;在基本作业上定义此行为,并在期望工作人员运行的作业上继承此行为。如果您对某些作业有“特殊”情况,并且没有破坏其他任何内容,那么这也允许您自定义行为
  • 假设您没有运行ActiveJob(因为没有提到它),请阅读
    delayed_job
    hooks:-它们可能是一个合适和/或有用的工具
  • 熟悉悲观锁定策略和乐观锁定策略的一些差异和权衡——这是一个很好的起点:
  • 阅读有关分布式锁概念的一般实践,以便为自己选择最佳工具和策略(它不必是一个疯狂的复杂解决方案,数据库中存储租户标识符的一个简单表就足够了,但您将要考虑失败案例——例如,如何管理被抛弃的锁)

认真考虑不这样做;系统是否确实需要严格地操作?如果是这样的话,它可能指示数据模型中的一个潜在缺陷,或者如何在数据周围构造转换。在考虑数据的操作时,要在应用程序中实现酸度,并且可以避免很多。se的问题。这是一个原因,它不是一个普遍可用的“开箱即用”后台工作运行人员的功能。如果有潜在缺陷,它不仅会在这个问题上咬你,还会在其他问题上咬你-保证!

如果你试图避免两个不同的工作人员在同一个租户上工作,那么这是一个糟糕的设计选择。有些东西很难闻。首先修复它。但是,如果你想要相同类型的工作人员实例在不同的公寓里工作是最简单的解决方法。这些关系是我的假设

ExpiredOrderCleaner = Struct.new(:tenant_id) do
  def perform
    Order.where(tenant_id: tenant_id).expired.delete_all
  end
end

Tenant.each do |tenant|
  Delayed::Job.enqueue ExpiredOrderCleaner.new(tenant.id)
end
这将为每个租户创建唯一的作业。单个工作实例将在特定租户上工作。但是,可能有其他类型的作业在同一租户上工作。这是最好的。如果需要更小的范围,只需为工作实例传递更多参数,并在查询中使用,并使用数据库事务以避免冲突美国

对于任何背景工作者来说都是如此

  • 使作业幂等且具有事务性意味着您的作业可以安全地执行多次
  • 接受并发性设计您的作业,以便并行运行大量作业

如果您使用gem和wrappers,您的工作会容易得多。请参阅这些文档中的示例。

这是否意味着您的系统中每个租户至少需要启动一个工作程序?除非每个租户都有自己的服务器,否则这听起来不是很容易扩展的。每个工作程序在内存中保存整个Rails应用程序。@Unixmonkey只保存正在运行的应用程序工人消耗内存,不是吗?不是计划的。我试图让一组工人一次只在不同的租户上工作。计划一个作业只意味着序列化运行作业所需的数据,并将其添加到
delayed_jobs
表中,通常仍有一组工人在空闲,等待拿起作业并处理它们。我如果您在计划作业的同时启动了一个工作程序,并让它在完成作业时自动终止,那么您可能会看到这一点,但这仍然会带来很大的开销,并且重试逻辑您可能需要自己重新实现。谢谢!我不知道延迟的作业挂钩工作得很好!我应用程序中的缺陷是我使用的API只是允许每个租户有一个连接。