Rails部署,每个客户端一个环境是正确的方式吗



我们的应用程序是医院的Saas,部署在一个生产服务器上(与linux+nginx+puma代码相同(,用于我们所有的客户。默认情况下,有三种:测试、开发和生产。但在我们的案例中,我们有10个环境配置文件指向文件夹"config/environments/"中的10个客户端配置文件。我们将医院名称赋予环境文件,例如

config/environments/hospital1.rb
config/environments/hospital2.rb
config/environments/hospital3.rb
...

付费有几个功能是用engine开发的。

现在想象一下,医院为特辑付费。如何仅为医院激活功能1?我目前正在Gemfile 中执行此操作

group :hospital1 do
gem 'feature1', path to ....
end

问题:这是将生产环境替换为客户端特定环境并能够在GEMFILE中启用/禁用gem的好方法吗?

欢迎任何建议!

这听起来是个坏主意。

你在这里"把桔子和沙发混在一起"。环境和客户端具有不同的语义。

您所拥有的要么是部署在不同服务器上的同一应用程序的不同实例(然后特定于客户端的内容应该来自环境变量(,要么是单个部署(看起来像是您的情况(,那么特定于客户端设置应该存储在数据库中。

至于限制访问付费功能,你应该考虑像专家这样的解决方案。Gemfile绝对不是适合您的业务逻辑的地方!

就我个人而言,我更喜欢将环境视为技术级别的东西,而不是应用程序逻辑的东西。因此,我会尽量减少环境。如果你想在Gemfile中有条件语句,也许最好使用环境变量?类似的东西

if ENV['FEATURE_1_ENABLED']
gem 'feature1', path to ....
end

您甚至可以通过每个医院有一个.env文件并用Dotenv.load加载适当的文件来自动管理这些变量。

这是一种非常糟糕的方法。

基本上,你试图同时处理多项事务,但方式非常奇怪和不受控制。

这是一个架构决策,它不适合StackOverflow的答案,许多人需要一整本书来解释它

看看https://rubygarage.org/blog/three-database-architectures-for-a-multi-tenant-rails-based-saas-app以获得一些视角。

基本上,功能启用/禁用应该基于规则进行,这些规则应该至少可以通过一些管理面板轻松管理。

按客户划分环境的方法不能很好地扩展。Gemfile绝对不是保存客户端设置的地方。而且测试起来也比较困难。

如果你需要强大的分离(独立的数据库、工人等(,我仍然会选择一个production环境:

  1. 有一个配置文件,其中包含所有客户端的设置(启用的功能等(:
hospital1:
name: Imaginary Medical Center
address: Nowhere st. 0
features:
cool_notifications: true
feature2: false
hospital2:
name: ObfuscatedView Commutinu Hospital
features:
feature1: false

稍后,它可以发展为管理数据库

  1. 而不是环境传递一个具有租户id的ENV变量(如HOSPITAL_NAME=hospital1 rails server -e production(,并生成一个singleton对象,该对象在调用时加载该配置
  2. 所有引擎都可以在gemfile中,但使用require: false,如果启用了相应的功能,则只能在application.rb中加载它们(就在Bundler.require之后(

如果你可以允许一些资源共享(比如网络工作者(,也可以看看公寓宝石。你必须为你的应用程序和功能切换添加多域支持,但处理不断增长的客户端数量会更容易(并节省服务器资源,很可能你的客户端都不会产生高持续负载(

最新更新