阅读更多

0顶
1踩

编程语言

转载新闻 如何提升 RailS 应用的性能?

2015-07-27 15:19 by 副主编 mengyidan1988 评论(2) 有6375人浏览



Is rails slow?
「铁路很慢」,你也许听过这个笑话,那么我们的 Rails 框架呢? 如果说 Rails 慢,那么如何提升 Rails APP 的性能就成了开发者们最关注的问题。

也许你听说过很多提升 RoR APP 性能的方法,它们有难有易,我们需要在选择其中最能帮助开发者脱离性能困境的。

这里列举了几种不同的提升 Rails 应用性能的方法。

1.数据库索引
你的 APP 被 DB 性能限制,优秀的数据库索引可以在大型数据库表中带给你100倍的性能提升。然而并非所有 Rails 开发者都明白这一点有多重要。
添加indexes很容易:
class AddIndexToClientIndustry < ActiveRecord::Migration
   def change
     add_index :client_industries, :client_id
   end
end

接下来就有无 Index 的情况做个对比。
有 Index 的情况:
CREATE INDEX 
 addresses_addressable_id_addressable_type_idx  ON
 addresses  USING btree  (addressable_id,addressable_type);
 t1 = Time.now
  c = Company.find(178389)
  a = c.addresses.first
 t2 = Time.now
 puts "---Operation took #{t2-t1} seconds---”

 Result with index:
 ---Operation took 0.012412 seconds---

没有 Index 的情况:
DROP INDEX
 addresses_addressable_id_addressable_type_idx;

t1 = Time.now
 c = Company.find(178389)
 a = c.addresses.first
t2 = Time.now
puts "---Operation took #{t2-t1} seconds---”

Result without index:
---Operation took 0.378073 seconds---

0.378073 / 0.012412 = 30.46 没有索引比有索引慢了30.46秒。

因此工程师可以在所有引用参数,或者其他经常查询的参数中加入 Indexes。但是不能加太多, 因为每一个都会增加 DB Size 从而影响性能。

2. 数据库查询数量
RoR让编程更快捷,但反过来也让每条请求的数据库查询次数难以控制。举个例子,如果每一个 Client 有一或多个 Industries。 我们想要显示 Client List 和它们的 Primary Industries:
<% @clients.each do |client| %>
  <tr>
      <td><%= client.id %></td>
      <td><%= client.business_name %></td>
      <td><%= client.industries.first.name %></td>
  </tr>
<% end %>

# app/controllers/clients_controller.rb
def index
    @clients = Client.all
end

如果有50个 Clients, 则会有51条数据库查询:
Processing by ClientsController#index as HTML
SELECT "clients".* FROM "clients" 
SELECT "industries".* FROM "industries" INNER JOIN "client_industries" ON "industries"."id" = "client_industries"."industry_id" WHERE "client_industries"."client_id" = 1 LIMIT 1
SELECT "industries".* FROM "industries" INNER JOIN "client_industries" ON "industries"."id" = "client_industries"."industry_id" WHERE "client_industries"."client_id" = 2 LIMIT 1
SELECT "industries".* FROM "industries" INNER JOIN "client_industries" ON "industries"."id" = "client_industries"."industry_id" WHERE "client_industries"."client_id" = 3 LIMIT 1
…

解决方案: Eager Loading
# app/controllers/clients_controller.rb
def index
    @clients = Client.includes(:industries).all
end

现在只有2至3条数据库查询而非51条:
Processing by ClientsController#index as HTML
SELECT "clients".* FROM "clients" 
SELECT "client_industries".* FROM
"client_industries" WHERE
"client_industries"."client_id" IN (1, 2, 3)
SELECT "industries".* FROM "industries" WHERE "industries"."id" IN (1, 5, 7, 8, 4)

3. 减少内存占用
  • 只用真正需要的gem
  • 使用时再加载对象
  • 分批处理海量数据。

一个使用真实数据的例子——find_each:
Using find:
t1 = Time.now  
Company.where(:country_id=>1).find do |c|
puts "do something!" if ['Mattski Test'].include?(c.common_name)
end
t2 = Time.now
puts "---Operation took #{t2-t1} seconds---”

Result:
1 query, taking 46.65 seconds

Now using find_each:
t1 = Time.now  
Company.where(:country_id=>1).find_each do |c|
      puts "do something!" if ['Mattski Test'].include?(c.common_name)
end  
t2 = Time.now
puts "---Operation took #{t2-t1} seconds---"

Result:
100 queries, taking 15.53 seconds in total (3x faster)

也有查询多了反而快的情况。

4. 使用缓存
缓存的使用对性能有巨大影响,首先确保数据模型正确,缓存可以帮你隐藏结构问题。
  • 对象缓存 在使用对象缓存的情况下,应该把查询方法的 include 去掉,避免关联查询无法利用缓存的现象。
  • 查询缓存 在不要求实时的情况下,对于统计类耗时查询,那么可以使用 memcache-client 将查询结果缓存到 memcached 里。
  • 页面局部缓存 对象缓存和查询缓存都会降低数据库访问负载,但如果 RoR 的负载很高,就只能依靠页面局部缓存了。

「web2.0网站比较常用使用页面局部缓存,Rails 的页面局部缓存有一个缺点,就是和页面查询结果对应的 Action 当中的查询语句要放在 View 里面,否则每次 Action 里面的查询还是会被执行,但是这样做会破坏程序代码良好的 MVC 结构。这种情况下,也可以采用另外一个 Cache 插件: better rails caching,在缓存页面的同时可以缓存 Action 当中的查询语句。」
5. 让Web请求更快
只有少量可用进程用于服务 web 请求,因此需要使 web 请求更快。理想情况下, web 进程一般在毫秒内完成,1至2秒算是慢的,10秒以上是非常慢的。如果你的 web 请求很慢,你的Rails APP 将无法支撑同一时间的大量用户。

解决方案:使用后台运行 对长时间运行的项目使用后台运行诸如 delayed jobs, 从而释放你的 web 进程来解决更多请求。
6.性能监控
对 APP 进行性能监控从而便于发现哪部分运行的慢,甚至快速定位到问题所在,可以利用国内应用性能监控做的最好的 OneAPM 监控工具。

OneAPM for Ruby 能够深入到所有 Ruby 应用内部完成应用性能管理和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。 追溯性能瓶颈至:性能表现差的 SQL 语句、第三方 API、Web Services、Caching Layers、后台任务等。



图为使用 OneAPM 进行监控的总览页面,在这里可以对请求在服务器端耗时有个初步印象。可以直观的看到不同时间 web 事物、后台任务、数据库和外部服务的平响应时间、吞吐量、执行次数等指标,图中 web 事物在15:41的时候响应时间出现峰值,响应速度较慢。



为了进一步确定问题所在,点进web事物界面可以进一步了解各慢事物响应时间占比,快速定位到 api/medicines/index 的响应时间较长。



点击错误的请求地址,将会列出该错误的 URL、第一次和最后一次发生时间、错误发生次数、监测到错误的 Agent 名称、错误信息和堆栈信息。

好的应用性能监控往往需要花大量的时间和精力实现,因此选择优秀的第三方监控工具将极大地提高运维效率,这对提升 Rails APP 性能有极大帮助。

7. 使用内存数据库
当查询和排序都在内存中完成,数据库将会运行的更快,而它们需要在磁盘上运行的时候就变得很慢。

解决方案:
  • 限制 DB 的大小,保证它完全适合内存。
  • 将不紧急的信息移出主要数据库,移入次要数据库或其他地方。
  • 如果有大量存储需求,考虑使用非关系型数据库。

8. 更多性能建议:
对静态文件使用内容分发网络,例如使用 AWS CloudFront。
对需要1-2秒的加载项使用延迟加载。
使用服务导向架构,使一些进程在托管栈同步进行。
相信选择一种或几种适合的性能提升方法,可以使 RoR APP 更令用户满意。

备注:本文参考并翻译了 Matt Kuklinski 在 slideshare 上关于 提升 Rails 性能所分享的部分内容。

本文系 OneAPM 工程师编译整理。OneAPM 是应用性能管理领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和 SQL 语句的实时抓取。想阅读更多技术文章,请访问 OneAPM 官方博客
  • 大小: 284.6 KB
  • 大小: 25.5 KB
  • 大小: 60.9 KB
  • 大小: 75.9 KB
来自: OneAPM
0
1
评论 共 2 条 请登录后发表评论
2 楼 diggywang 2015-07-29 12:28
这些手段,貌似使用所有语言,和框架无关
1 楼 kaopuso 2015-07-27 19:49
不错 非常感谢  分享一下 redis资源 [url=http://kaopu.so/redis]redis学习资料[url]

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • rails_performance:监视您的Rails应用程序的性能

    一个自托管的工具,用于监视Ruby on Rails应用程序的性能。 这是New Relic APM,Datadog或其他类似服务的简单免费替代品。 它允许您跟踪: 吞吐量报告(请参阅RPM数量(每分钟的请求数)) 平均响应时间 最慢的...

  • 怎样提升 RailS 应用的性能?

    Is rails slow? 「铁路非常慢」,你或许听过这个笑话,那么我们的 Rails 框架呢?...假设说 Rails 慢,那么怎样提升 Rails APP 的性能就成了开发人员们最关注的...这里列举了几种不同的提升 Rails 应用性能的方...

  • 提升Ruby on Rails性能的几个解决方案

    简介 Ruby On Rails 框架自它提出之日...Rails 是一个真正彻底的 MVC(Model-View-Controller) 框架,Rails 清楚地将你的模型的代码与你的控制器的应用逻辑从 View 代码中分离出来。Rails 开发人员很少或者可能从未遇到

  • app_profiler:收集Rails应用程序的性能配置文件

    AppProfiler旨在为Rails应用程序提供性能分析的通用框架。 安装 要安装app_profiler您需要将其包含在Gemfile 。 分析中间件 组态 这个gem自动将AppProfiler::Middleware中间件注入到Rails应用程序中。 可以使用...

  • powerstation:用于检测Rails应用程序中的性能错误的工具

    动力站是一种工具,可以发现Rails应用程序中的性能错误,例如API滥用,重复查询等。使用工具有两种使用Powerstation的方法: 作为RubyMine插件,您可以。 源代码包含在此存储库中的powerstation/IDE_plugin 。 作为...

  • Rails中使用MySQL分区表一个提升性能的方法

    MySQL 的分区表是一种简单有效的处理极大数据表的特性,通过它可以使应用程序几乎很少改动就能达成对极大数据表的高效处理,但由于 Rails ActiveRecord 设计上一些惯例,可能导致一些数据处理不能利用分区表特性,...

  • rorvswild:Ruby on Rails应用监视:Rails开发人员的性能和异常见解

    狂野狂暴 RoRvsWild是Ruby,可以监视Ruby on Rails应用程序中的性能和异常。 这种宝石具有双重模式,可以开发和生产。 无需帐户即可使用它来监视您的请求在开发环境中的性能。 也可以通过上的帐户在生产和暂存环境中...

  • Rails应用性能优化一例

    Rails是一款经典的Web开发框架,它的许多设计思想...对于大多数创业型公司的初级产品来说,还不值得动用复杂缓存机制或者迁移数据库来进行优化,此时针对Rails应用本身的一些低效代码进行优化,往往就能取得很好的效果

  • Ruby on Rails已死?GitLab:我还在用呢!

    “Ruby on Rails已死”言论甚嚣尘上后的三年,GitLab还没放弃它!

  • influxdb-metrics:使用InfluxDB跟踪Rails应用程序的性能指标

    InfluxDB :: Metrics 新增功能可让您的Rails应用程序报告数据库查询的性能指标以及对InfluxDB的响应时间。安装将此行添加到您的应用程序的Gemfile中: gem 'influxdb-metrics' 如果您使用的是InfluxDB的8.x行,则也...

  • rails-perftest:对Rails应用进行基准测试和配置

    性能测试Rails应用 本指南涵盖了各种性能测试Ruby on Rails应用程序的方法。 阅读本指南后,您将知道: 各种类型的基准测试和性能分析指标。 如何生成性能和基准测试。 如何安装和使用GC修补的Ruby二进制文件来...

  • terraforming-rails:Terraforming旧版Rails应用指南和工具

    宝石测验 –分析和改善测试套件性能安全 –检查已知CVE的依赖性–检测应用程序代码的安全性问题数据库 –与数据库约束一致的验证检查数据库约束和模型验证的一致性–检测具有副作用的交易(非原子交易)消除死代码 ...

  • 对优化Ruby on Rails性能的一些办法的探究

    1.导致你的 Rails 应用变慢无非以下两个原因: 在不应该将 Ruby and Rails 作为首选的地方使用 Ruby and Rails。(用 Ruby and Rails 做了不擅长做的工作) 过度的消耗内存导致需要利用大量的时间进行垃圾回收。 ...

  • 窥视:窥探您的Rails应用程序

    窥视 看一下您的Rails应用程序。 这是最初在GitHub上构建的概要分析工具,旨在帮助我们深入了解我们的应用程序。 现在,我们将其提取到Peek中,以便其他Rails应用程序也可以享受到相同的好处。 Peek在您的应用程序...

  • redis-search:已弃用! 高性能实时前缀搜索,索引存储在Redis for Rails应用程序中

    ) 高性能实时前缀搜索,索引在Redis的存储Rails应用程序。注意! 有更多更好的方法可供选择!下面的两种方式将是更好的选择:主人身份产品特点即时搜寻高性能前缀匹配搜索支持别名匹配支持ActiveRecord和Mongoid 按...

  • 九个衡量 Rails 应用性能的小方法

    后来,你雇了一群天赋异禀的开发者、Web 设计师和用户体验专家,他们用一种非常棒的框架——Ruby on Rails 帮你实现长久以来的梦想。你的网站诞生了!但是,不幸的是,你没有足够的资金用于搭建完善的服务器,你只是...

  • go-on-rails:使用Rails开发或生成Golang应用程序

    使用Rails生成Golang代码或管理Go应用开发go-on-rails是Rails生成器,旨在: 帮助开发和集成一些用Golang编写的API到现有的Rails应用程序,以实现高性能使用您熟悉的Rails工具开发和管理Golang应用程序项目将不太...

  • setting.xml文件,修改Maven仓库指向至阿里仓

    setting.xml文件,修改Maven仓库指向至阿里仓

  • 基于java的玉安农副产品销售系统的开题报告.docx

    基于java的玉安农副产品销售系统的开题报告

Global site tag (gtag.js) - Google Analytics