Ruby on Rails的可伸缩性/性能?

我已经使用了一段时间的PHP,并使用CodeIgniter,这是一个伟大的框架。 我开始一个新的个人项目,上次我正在考虑使用什么(PHP与ROR)我使用PHP是因为我听到了ROR的可伸缩性问题,尤其是在阅读了Twitter开发者对此的评论之后。 可扩展性在ROR中还是一个问题,还是有改进的地方?

我想学习一门新的语言,ROR看起来很有趣。 PHP完成工作,但每个人都知道它的语法和组织非常糟糕,感觉像是一个大问题。

为了扩大Ryan Doherty的回答,有点…

我在日常工作(.NET / C#)中使用静态types的语言,以及Ruby作为副作用。 在我目前的日常工作之前,我是为纽约时报整合服务工作的ruby开发公司的首席程序员。 在此之前,我也在PHP工作(虽然很久以前)。

我只是简单地说:我经历过rails(更一般的ruby)性能问题,还有一些其他的select。 正如瑞安所说,你不会自动为你量身定做。 它需要工作和巨大的耐心来find你的瓶颈。

我们从其他人甚至我们自己看到的大多数性能问题都是在我们的ORM层中处理性能低下的查询。 我们从Rails / ActiveRecord到Rails / DataMapper,最后到Merb / DM,每一次迭代都会因为底层框架的原因而变得更快。

caching对于性能确实有惊人的奇迹。 不幸的是,我们无法caching我们的数据。 我们的caching最多每五分钟就会有效无效。 我们的网站几乎每一个位都是dynamic的。 所以如果/当你不能这样做,也许你可以从我们的经验中学习。

我们不得不认真调整数据库索引,确保我们的查询不是做了非常愚蠢的事情,确保我们没有执行比绝对必要的更多的查询等等。当我说“非常愚蠢的事情”时,我意思是1 + N查询问题…

#1 query Dog.find(:all).each do |dog| #N queries dog.owner.siblings.each do |sibling| #N queries per above N query!! sibling.pets.each do |pet| #Do something here end end end 

DataMapper是处理上述问题的好方法( 不存在1 + N的问题 ),但更好的办法是用你的大脑,停止这样的查询:D当你需要原始的性能,大部分的ORM层不会轻易处理非常自定义的查询,所以你可以手写他们。

我们也做了常识的事情。 我们为我们不断增长的数据库购买了一台健壮的服务器,并将它移到了它自己的专用盒子上。 我们也不得不经常进行数据处理和数据导入。 我们把处理过程也搬到了自己的盒子里。 我们也停止加载我们的整个吓人的堆栈,只为我们的数据导入工具。 我们高雅地加载了我们绝对需要的东西(从而减less了内存开销!)。

如果你不能告诉…一般来说,当涉及到ruby / rails / merb,你必须扩大规模,抛出硬件的问题。 但最终硬件便宜, 虽然这是不好的代码的借口! :d

即使有这些困难,如果我能帮到的话,我个人也绝不会在另一个框架中开始项目。 我爱上了这门语言,每天都不断地学习。 这是我从C#得不到的,尽pipeC#更快。

我也喜欢开源工具,用语言开始工作的低成本,低成本去找东西,试着去看看它是否可以销售,并且一直用一种经常可以优雅和美丽的语言工作…

最终,就select你的框架而言,这就是你想要的生活,呼吸,吃饭和睡眠。 如果你喜欢微软的思维方式,去.NET。 如果你想开源,但仍然想要结构,尝试Java。 如果你想有一个dynamic的语言,仍然有比ruby更多的结构,尝试python。 如果你想要优雅,试试Ruby(我小子,我小子…还有其他很多优雅的语言都适合这个法案,不要试图开始一场火焰战争:D)

地狱,尝试一切! 我倾向于同意上面的答案,担心优化早期不是你应该或不应该select框架的原因,但我不同意这是他们唯一的答案。

所以总而言之,是的,你必须克服困难,但语言的优雅,imho,远远超过了这些缺点。

对不起,这本小说,但我一直在那里和性能问题。 它可以克服。 所以不要让这个吓跑你

RoR与许多大型网站一起使用,但是与任何语言或框架一样,它需要一个很好的体系结构(db缩放,caching,调优等)来扩展到大量的用户。

RoR有一些小的变化,使其更容易扩展,但不要期望它能为您提供神奇的规模。 每个网站都有不同的缩放比例问题,所以你必须投入一些工作来扩大规模。

开发将为您的项目带来成功的最佳机会的技术 – 快速开发,易于debugging,易于部署,良好的工具,您知道它里面(除非重点是学习一种新的语言),等等。

如果你每个月得到几千万的独特用户,你总是可以聘请几个人,如果你需要,你可以用不同的技术来重写。

…你会在caching中 (对不起 – 无法抗拒!)

首先,将Rails与Symfony,CodeIgniter或CakePHP进行比较可能会更有意义,因为Ruby on Rails是一个完整的Web应用程序框架。 与PHP或PHP框架相比,Rails应用程序具有体积小,清晰易读的优点。 PHP非常适合小型个人页面(最初代表“个人主页”),而Rails是一个完整的MVC框架,可用于构build大型站点。

Ruby on Rails与可比的PHP框架相比, 还没有一个更大的可伸缩性问题。 如果只有适量的用户(10,000-100,000)在类似数量的对象上运行,则Rails和PHP都可以很好地扩展。 对于几千个用户来说,经典的单片架构就足够了。 有了一点M&M(Memcached和MySQL),你也可以处理数百万个对象。 M&M体系结构使用MySQL服务器来处理写入,使用Memcached来处理高读取负载。 传统的存储模式,使用规范化关系表的单个SQL服务器(或者至多是SQL主/多个读取从设置)不再适用于非常大的站点。

如果您拥有Google,Twitter和Facebook等数十亿用户,那么分布式架构可能会更好。 如果你真的想无限扩展你的应用程序,可以使用某种便宜的商品硬件作为基础,将你的应用程序划分为一组服务,保持每个组件或服务本身可扩展(将每个组件devise成一个可扩展的服务)架构到您的应用程序。 然后,您将需要合适的可伸缩数据存储,如NoSQL数据库和分布式哈希表(DHT),您将需要复杂的map-reducealgorithm来处理它们,您将不得不处理SOA,外部服务和消息传递。 PHP和Rails都没有在这里提供一个灵丹妙药。

与RoR的区别在于,除非你在Alexa排名前100位,否则你不会有任何可扩展性问题。 除非您可以将Phusion,Passenger或Mongrel挤出来,否则共享主机的稳定性将会有更多问题。

花一点时间看一下Twitter用户需要处理的问题,然后问自己,你的应用是否需要扩展到这个水平。

然后在Rails中构build它,因为你知道它是有道理的。 如果您使用的是Twitter级别的卷,那么您将会考虑性能优化选项。 至less你会用一种很好的语言来应用它们!

你不能比较PHP和ROR,PHP是一种像Ruby一样的脚本语言,而Rails是一个像CakePHP一样的框架。
我强烈build议你使用Rails,因为你将有一个严格按照MVC模式组织的应用程序,这对你的可伸缩性要求是必须的。 (使用PHP,你必须自己关心项目组织)。
但是对于可伸缩性呢,Rails不仅仅是MVC:例如,你可以开始用数据库开发你的应用程序,而不需要任何努力(在绝大多数情况下)在路上改变它,所以我们可以声明一个Rails应用程序(几乎)是数据库独立的,因为它是ORM(允许你避免数据库查询),你可以做很多其他的东西。
(看看这个videohttp://www.youtube.com/watch?v=p5EIrSM8dCA )

只是想添加一些更多的信息,基思·汉森的聪明点1 + N问题,他说:

DataMapper是处理上述问题的好方法(不存在1 + N的问题),但更好的办法是用你的大脑,停止这样的查询:D当你需要原始的性能,大部分的ORM层不会轻易处理非常自定义的查询,所以你可以手写他们。

学说是最受欢迎的PHP ORM之一。 它通过提供称为Doctrine Query Language(DQL)的语言来解决ORM固有的1 + N复杂性问题。 这允许您编写像使用您现有的模型关系的SQL语句。 例如

从(ModelA m) – > leftJoin(m.ModelB) – > execute()中select(*) – >

我从这个线程得到的印象是,ROR的可伸缩性问题主要归结为ORM在加载子对象方面的混乱 – 即上面提到的“1 + N”问题。 在上面的例子中,瑞恩给狗和业主:

 Dog.find(:all).each do |dog| #N queries dog.owner.siblings.each do |sibling| #N queries per above N query!! sibling.pets.each do |pet| #Do something here end end end 

你实际上可以编写一个单一的sql语句来获得所有的数据,你也可以将这些数据拼接到Dog.Owner.Siblings.Pets对象中。 但是有人能写一个自动完成这个操作的ORM,所以上面的例子会导致数据库和单个SQL语句的一次往返,而不是数百次? 完全。 只需将这些表join一个数据集,然后执行一些逻辑即可将其拼接起来。 把这个逻辑通用化是一个棘手的问题,所以它可以处理任何一组对象,但不能处理世界末日。 最后,表和对象只有三个类别(1:1,1:很多,很多)中的一个相互关联。 只是没有人build立这个ORM。

你需要一个语法,告诉系统预先为这个特定的查询加载哪些子项。 您可以通过“急切”加载LinqToSql(C#)(这不是ROR的一部分)来做到这一点,但即使这会导致数据库往返一次,仍然会有数百个单独的SQL语句目前已经成立。 这更多的是关于ORM的历史。 他们刚开始走错了路,从来没有真正恢复过。 “延迟加载”是大多数ORM的默认行为,也就是说每提到一个子对象就会引发另一次往返,这太疯狂了。 然后用'急切'的加载 – 加载孩子的前面,这是静静地设置在LinqToSql以外的所有我知道的东西 – 即哪些孩子总是加载某些对象 – 就像你总是需要加载一个集合时加载相同的孩子的狗。

你需要某种强types的语法,说这次我想加载这些孩子和孙子。 也就是说:

 Dog.Owners.Include() Dog.Owners.Siblings.Include() Dog.Owners.Siblings.Pets.Include() 

那么你可以发出这个命令:

 Dog.find(:all).each do |dog| 

ORM系统会知道需要join哪些表格,然后将结果数据拼凑成OM图层。 确实,你可以把硬件放在目前我普遍赞成的问题上,但是ORM(例如Hibernate,Entity Framework,Ruby ActiveRecord)不应该被写得更好。 硬件实际上并没有把你从一个往返行程100个SQL语句查询中解救出来,而这个查询应该是一个往返行程和一个SQL语句。