简体   繁体   English

Rails Engines可伸缩性问题

[英]Rails Engines scalability issue

I need to find a way for scaling my rails monolith application with the help of rails engines. 我需要找到一种在rails引擎的帮助下扩展我的rails monolith应用程序的方法。

Goal: I have database connection timeout issue and monolith has more than 200+ models. 目标:我有数据库连接超时问题,Monolith具有200多个模型。 what we want to do is divide our models into the tree-like structure of engines. 我们要做的就是将我们的模型分成树状的引擎结构。 and we will be able to use a separate database for each engine. 而且我们将能够为每个引擎使用单独的数据库。

UseCase: let's say we have engine A as the base engine and which is included in engine B and C respectively. 用例:假设我们有引擎A作为基本引擎,并且分别包含在引擎B和C中。 Both B and C engines live on the same level of the tree. B和C引擎都位于树的同一级别上。

So i have models seggrated in different engines. 因此,我将模型安装在不同的引擎中。

Engine A: has all data related to user. 引擎A:具有与用户相关的所有数据。

Class User 
end

Engine B: has all data related to products 引擎B:具有与产品相关的所有数据

class Product
end

Engine C: has all data related to reports. 引擎C:具有与报表相关的所有数据。

class Report
end

now the main issue comes while defining the associations . 现在主要问题出现在定义关联时 earlier we were having associations and several other methods which access associations. 之前,我们有关联以及访问关联的其他几种方法。 For eg. 例如。

class User
  has_many products

  def get_title_product
    products.pluck(:title)
  end
end

now I cannot define it in engine A as products table doesn't live there. 现在我无法在引擎A中定义它,因为产品表不存在于那里。

Option: what I know is I have to open that User model inside Engine B and define all the association and get_title_product logic related to this Domain in engine B itself. 选项:我所知道的是,我必须在引擎B中打开该用户模型,并在引擎B本身中定义与此域相关的所有关联和get_title_product逻辑。 I can't even include Engine B in Engine A because it will result in circular dependency. 我什至不能将Engine B包含在Engine A中,因为它将导致循环依赖。

I don't want to follow above approach because it will get messy and my application is significantly large, additionally I don't think it is good as per rails best practices. 我不想遵循上述方法,因为它会变得凌乱并且我的应用程序很大,此外,按照Rails的最佳实践,我也不认为这是好方法。

Thanks in advance. 提前致谢。

Your post contains many questions. 您的帖子包含许多问题。 Your asking about database sharding, architecture with rails engines and performances / scalability with the timeout issue. 您询问有关数据库分片,具有Rails引擎的体系结构以及具有超时问题的性能/可伸缩性的信息。

Performances / Timeout 表演/超时

First your timeout issue is not related to the number of models as you suggest. 首先,您的超时问题与您建议的型号数量无关。 The number of models as no impact at all on performances. 型号数量对性能完全没有影响。 To know where is the performance problem or the bottleneck you should use a monitoring tool. 要了解性能问题或瓶颈在哪里,您应该使用监视工具。 This one is my favorite https://www.rorvswild.com (DISCLAIMER: I'm the author ^_^). 这是我最喜欢的 https://www.rorvswild.com (免责声明:我是作者^ _ ^)。 There is other competitors, use the one your like more. 还有其他竞争对手,请更多使用您喜欢的一个。

For the timeouts maybe you should check around your database config. 对于超时,也许您应该检查一下数据库配置。 We have not enough informations here to go deeper. 我们没有足够的信息来深入了解。

Database sharding 数据库分片

That is not trivial at all since you cannot JOIN and reference foreign keys when they are not in the same db. 这根本不是一件容易的事,因为当它们不在同一数据库中时,您无法联接和引用外键。 That is why you have to carefully chose where to shard your db. 因此,您必须仔细选择将数据库分片的位置。 Ideally it's where you have the least joins. 理想情况下,这里的联接最少。 It's a long work which has an important impact on your code base. 这项工作很长,对您的代码库有重要影响。 A stack overflow post is not enough to talk about sharding. 堆栈溢出文章不足以谈论分片。 Fortunately there is a lot of articles and gems to help you for that. 幸运的是,有很多文章和宝石可以帮助您。

Just be sure you understand that you can split the load across many databases, but it comes at an extra price on your code base. 只需确保您了解可以将负载分散到许多数据库中即可,但这会给代码库带来额外的费用。

For the relationships across databases you cannot use the Rails builtin has_many and so on. 对于跨数据库的关系,您不能使用Rails内置的has_many等。 You have to define the relationships yourself or use a gem which will help for that. 您必须自己定义关系,或者使用宝石将对此有所帮助。 To give you an idea: 给您一个想法:

class User
  def products
    Product.where(user_id: id)
  end
end

Rails engines Rails引擎

They are great to built reusable piece of features across applications ( http://guides.rubyonrails.org/engines.html ). 它们对于在整个应用程序中构建可重用的功能非常有用( http://guides.rubyonrails.org/engines.html )。 Looks like reusing is not your goal. 看起来重用不是您的目标。 So I'm afraid your going in the wrong direction. 因此,恐怕您走错了方向。

If you don't want to reopen the class you can use a module: 如果您不想重新打开类,可以使用一个模块:

module HasProducts
  def self.included(model)
    model.has_many(:products)
  end

  def get_title_product
    products.pluck(:title)
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM