如何在Ubuntu12.04LTS上将Memcached与RubyonRails一起使用
状态: 已弃用
本文介绍了不再受支持的 Ubuntu 版本。 如果您当前正在运行运行 Ubuntu 12.04 的服务器,我们强烈建议您升级或迁移到受支持的 Ubuntu 版本:
原因: Ubuntu 12.04 已于 2017 年 4 月 28 日终止生命周期 (EOL) and no longer receives security patches or updates. This guide is no longer maintained.
请参阅:
本指南可能仍可用作参考,但可能不适用于其他 Ubuntu 版本。 如果可用,我们强烈建议使用为您正在使用的 Ubuntu 版本编写的指南。 您可以使用页面顶部的搜索功能来查找更新的版本。
介绍
Memcached 是一个非常快速的内存对象缓存系统,它可以使 Rails 运行得更快,只需很少的更改。
先决条件:
本教程假设您已经安装了 Ruby on Rails 和 Memcached。 如果没有,教程链接如下:
- 如何使用 RVM 在 Ubuntu 12.04 LTS(Precise Pangolin)上安装 Ruby on Rails | 数字海洋
- 如何在 Ubuntu 12.04 上安装和使用 Memcache | 数字海洋
它还假设您的 Rails 应用程序已启动并正在运行,并准备好使用 Memcached 进行优化。
安装达利宝石
我们要做的第一件事是安装 Mike Perham's Dalli Gem:
gem install dalli
如果您使用 Bundler,则将 gem 'dalli'
添加到您的 Gemfile 并运行 bundle install
。
这将是我们与 Memcached 交互的超快速且功能丰富的方式。
配置 Rails
将 Rails 配置为使用 memcached 的第一步是编辑您的 config/environments/production.rb
并添加此行以告诉 Rails 使用 Dalli:
config.cache_store = :dalli_store
接下来,我们将告诉 ActionController 执行缓存。 将此行添加到同一文件中:
config.action_controller.perform_caching = true
现在,像往常一样重新启动 Rails 应用程序。
更改您的 Rails 应用程序
为了利用我们刚刚所做的更改,需要更新 Rails 应用程序。 有两种主要方法可以利用 memcached 为您提供的加速。
添加缓存控制标头
利用 memcached 的最简单方法是将 Cache-Control 标头添加到您的操作之一。 这将使 Rack::Cache 为您将该操作的结果存储在 memcached 中。 如果在 app/controllers/slow_controller.rb
中有以下动作:
def slow_action sleep 15 # todo - print something here end
我们可以添加以下行来告诉 Rack::Cache 将结果存储五分钟:
def slow_action expires_in 5.minutes sleep 15 # todo - print something here end
现在,当您第二次执行此操作时,您会发现它明显更快。 Rails 只需每五分钟执行一次即可更新 Rack::Cache。
请注意,这会将 Cache-Control 标头设置为公共。 如果您有某些只有一位用户可以看到的操作,请使用 expires_in 5.minutes, :public => false
。 您还必须确定缓存响应的适当时间,这因应用程序而异。
如果您想了解有关 HTTP 缓存的更多信息,请查看 Mark Nottingham ' 的 Web 作者和网站管理员缓存教程 。
在 Memcached 中存储对象
如果您有一个非常昂贵的操作或每次都必须创建的对象,您可以在 memcached 中存储和检索它。 假设您的操作如下所示:
def slow_action slow_object = create_slow_object end
我们可以通过更改如下操作将结果存储在 memcached 中:
def slow_action slow_object = Rails.cache.fetch(:slow_object) do create_slow_object end end
Rails 将向 memcached 请求带有 'slow_object' 键的对象; 如果它没有找到该对象,它将执行给定的块并将对象写回其中。
片段缓存
片段缓存是 Rails 的一项功能,可让您选择应用程序的哪些部分最动态且需要优化。 您可以轻松地将视图周围的任何部分缓存在 cache
块中:
<% # app/views/managers/index.html.erb %> <% cache manager do %> Manager's Direct Reports: <%= render manager.employees %> <% end %> <% # app/views/employees/_employee.html.erb %> <% cache employee do %> Employee Name: <%= employee.name %> <%= render employee.incomplete_tasks %> <% end %> <% # app/views/tasks/_incomplete_tasks.html.erb %> <% cache task do %> Task: <%= task.title %> Due Date: <%= task.due_date %> <% end %>
上述技术被称为俄罗斯娃娃缓存,暗指传统的俄罗斯套娃。 然后 Rails 会将这些片段缓存到 memcached 中,并且由于我们将模型添加到 cache
语句中,因此该缓存对象 ' 的键将在对象更改时更改。 但是,这产生的问题是任务更新时:
@todo.completed! @todo.save!
由于我们将缓存对象嵌套在缓存对象中,Rails 不会知道依赖此模型的缓存片段是否过期。 这就是 ActiveRecord touch
关键字派上用场的地方:
class Employee < ActiveRecord::Base belongs_to :manager, touch: true end class Todo < ActiveRecord::Base belongs_to :employee, touch: true end
现在,当 Todo
模型更新时,它将过期其缓存片段并通知 Employee
模型它也应该更新其片段。 然后 Employee
片段将通知 Manager
模型,在此之后,缓存过期过程完成。
俄罗斯娃娃缓存为我们带来了另一个问题。 部署新应用程序时,Rails 不知道何时检查视图模板是否已更改。 如果我们更新我们的任务列表视图部分:
<% # app/views/tasks/_incomplete_tasks.html.erb %> <% cache task do %> Task: <%= task.title %> Due Date: <%= task.due_date %> <p><%= task.notes %></p> <% end %>
Rails 不会使使用局部视图的缓存片段过期。 在您必须将版本号添加到 cache
语句之前,但现在有一个名为 cache_digests 的 gem,它会自动将模板文件的 MD5 哈希添加到缓存键中。 如果更新部分并重新启动应用程序,缓存键将不再匹配,因为视图模板文件的 MD5 已更改,Rails 将再次呈现该模板。 它还处理模板文件之间的依赖关系,因此,在上面的示例中,如果 _incomplete_tasks.html.erb
更新,它将使依赖链上的所有缓存对象过期。
此功能自动包含在 Rails 4.0 版中。 要在 Rails 3 项目中使用此 gem,请输入以下命令:
gem install cache_digests
或者,如果您使用 Bundler,请将此行添加到您的 Gemfile:
gem 'cache_digests'
高级 Rails 和 Memcached 设置
Dalli Ruby Gem 非常强大,它负责在 memcached 服务器集群中传播密钥,从而分配负载并增加 memcached 容量。 如果您的 Web 层中有多个 Web 服务器,您可以在每个服务器上安装 memcached 并将它们全部添加到您的 config/environments/production.rb
:
config.cache_store = :dalli_store, 'web1.example.com', 'web2.example.com', 'web3.example.com'
这将使用 一致性哈希 将密钥分布在可用的 memcached 服务器上。