Rails 多租户、作用域、类变量和线程安全

发布于 2024-11-29 10:00:58 字数 954 浏览 1 评论 0原文

简短版本

类变量在控制器操作期间是线程安全的吗?

长版本

我正在编写一个 Rails 3 应用程序,它使用单个数据库架构来实现多租户,每个表中都有 tenant_id 列来标识数据属于谁。

当然,我需要一种方法来确定在数据库上运行的所有查询的范围,以确保每个租户对数据的访问得到正确隔离。

有几个人建议通过始终通过租户实例访问数据库来实现此目的,例如:

current_tenant.associate_collection.where(...)

等。

但是,由于多租户是一个体系结构问题(而不是业务领域问题),所以我更愿意通过全局设置范围来尽可能保持模型的透明性。它也更干燥。

我发现我可以使用 多租户 gem 和 around_filters 来做到这一点:

class ApplicationController
  around_filter do
    Multitenant.with_tenant current_tenant
      yield
    end
  end
end

这会操纵 default_scope< /code> 适当的模型,以便所有数据访问自动限定在当前租户范围内。

这在开发中效果很好,但我担心线程安全。 Multitenant.with_tenant 在类变量中保留 current_tenant 引用。

问题是当控制器操作位于堆栈上时我可以依赖该变量的完整性吗?或者它是否会被另一个请求破坏?

另外,关于 Rails 中一般并发问题的好来源是什么?

Short Version

Are class variables thread-safe for the duration of a controller action?

Long Version

I'm writing a Rails 3 app that implements multi-tenancy using a single database schema with tenant_id columns in each table to identify to whom the data belongs.

Naturally I need a way to scope all queries that are run on the database to ensure that access to data is properly isolated per-tenant.

Several people have suggested achieving this by always accessing the database through the tenant instance, e.g.:

current_tenant.associate_collection.where(...)

etc.

However, since multi-tenancy is an architectural concern (not a business domain concern), I'd prefer to keep this as transparent to the model as possible by setting it up the scope globally. It's also much DRYer.

I've found I can do this using the multitenant gem and around_filters:

class ApplicationController
  around_filter do
    Multitenant.with_tenant current_tenant
      yield
    end
  end
end

This manipulates the default_scope of the appropriate models so that all data access is automatically scoped to the current tenant.

This works great in development, but I have concerns about thread safety. Multitenant.with_tenant preserves the current_tenant reference in a class variable.

The question is can I rely on the integrity of that variable while the controller action is on the stack? or could it be corrupted by another request?

Also, what’s a good source on general concurrency issues in Rails?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

以歌曲疗慰 2024-12-06 10:00:58

这不是持续时间的问题,并且控制器没有任何特殊之处使其成为原子(不可中断)代码序列。线程安全是关于理解锁、同步和线程调度程序。

在这种情况下,我认为你的问题甚至不是 Rails 特有的。一般来说,线程安全是通过在写入时锁定数据并在写入完成时解锁来实现的。如果您熟悉的话,它与数据库锁定机制非常相似。

对于专注于 Ruby 的良好参考,我会访问这里: http://www.rubycentral.com /pickaxe/tut_threads.html

有关线程安全概念的更多信息(毕竟,线程在操作系统级别运行,因此更多的是了解线程安全在任何程序中如何工作),我会转到这里:<一个href="http://en.wikipedia.org/wiki/Thread_safety" rel="nofollow">http://en.wikipedia.org/wiki/Thread_safety

It's not a matter of duration, and there isn't anything special about a controller that makes it an atomic (uninterruptible) sequence of code. Thread safety is about understanding locks, synchronization, and the thread scheduler.

I don't think your question is even Rails specific in this case. In a general sense, thread safety is achieved through locking data while a write is happening, and unlocking it when the write is finished. It's very similar database locking mechanisms, if you're familiar with those.

For a good reference that focuses on Ruby, I would go here: http://www.rubycentral.com/pickaxe/tut_threads.html

For more info about the concept the thread safety (threads run at the OS level, after all, so it's more about understanding how thread safety works in any program), I would go here: http://en.wikipedia.org/wiki/Thread_safety

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文