Rails 多租户、作用域、类变量和线程安全
简短版本
类变量在控制器操作期间是线程安全的吗?
长版本
我正在编写一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这不是持续时间的问题,并且控制器没有任何特殊之处使其成为原子(不可中断)代码序列。线程安全是关于理解锁、同步和线程调度程序。
在这种情况下,我认为你的问题甚至不是 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