将在Docker中启动的Rails缓存存储设置为Redis
我正在使用docker-compose来启动一个作为API的Rails服务器并从React编写的前端调用API的配置来开发应用程序。
以下是关于为了减轻API负载而引入Redis缓存查询结果的备忘录。请注意,本文不涉及使用Docker和docker-compose进行环境设置以及Redis概述。
开发环境
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.1
BuildVersion: 19B88
$ docker -v
Docker version 19.03.1, build 74b1e89
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b
Redis的引入之前
FROM ruby:2.6.5-slim
# db, js関係の環境をインストール
RUN apt-get update -qq && apt-get install -y mariadb-client libmariadb-dev-compat build-essential apt-transport-https curl imagemagick && \
curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
apt-get install -y nodejs && \
curl -sS http://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
# Rails (bundle install)
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
version: "3"
services:
web:
build: .
command: /bin/sh -c "rm -f /myapp/tmp/pids/server.pid && bundle exec rails s -p '3001' -b '0.0.0.0'"
environment:
- DATABASE=myapp_development
- DATABASE_USER=root
- DATABASE_PASSWORD=password
- DATABASE_HOST=db
volumes:
- .:/myapp
ports:
- 3001:3001
depends_on:
- db
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
environment:
- MYSQL_DATABASE=myapp_development
- MYSQL_ROOT_USER=root
- MYSQL_ROOT_PASSWORD=password
volumes:
- mysql_vol:/var/lib/mysql
ports:
- 3306:3306
volumes:
mysql_vol:
Rails.application.configure do
# 略
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
# 略
end
引入Redis
1. 启用缓存
先ほど載せたDockerfileを除く2つのファイルを編集する
…前に, 先にやっておくことがあります!!
config/environments/development.rb のコメントにあるように,
Railsのdevelopment環境ではデフォルトでキャッシュが無効になっているのです.
これに気付かず, かなりハマってました…?
启用/禁用缓存。默认情况下,缓存被禁用。
运行rails dev:cache命令来切换缓存状态。
所以,会按照所写的命令直接执行。
$ docker-compose run web rails dev:cache
Starting myapp_db_1 ... done
Development mode is now being cached.
创建Redis容器
在使用docker-compose启动的容器中添加Redis。
version: "3"
services:
web:
# 略
depends_on:
- db
+ - redis
db:
# 略
+ redis:
+ image: redis
+ ports:
+ - 6379:6379
+ volumes:
+ - "./app/redis:/data"
volumes:
mysql_vol:
3. 设置缓存存储
在添加所需的gem到Gemfile后,进行构建并运行bundle install命令。
# 略
+ gem 'redis'
+ gem 'redis-rails'
$ docker-compose build
将Rails中的缓存目标指定为先前添加的Redis容器。
为了进行后续的操作确认,将保存期限设置为较短时间。
Rails.application.configure do
# 略
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true
- config.cache_store = :memory_store
+ config.cache_store = :redis_store, 'redis://redis:6379/0', { expires_in: 1.minute }
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
# 略
end
设定已经完成了 ?
4. 確認行動情況
Redis容器
首先重新启动容器,确保Redis容器正常运行。
在容器内附加并启动redis-cli,如果可以执行以下Redis命令,则表示ok。
$ docker-compose up -d
Creating myapp_db_1 ... done
Creating myapp_redis_1 ... done
Creating myapp_web_1 ... done
$ docker exec -it myapp_redis_1 /bin/bash
root@05aaca0b40db:/data# redis-cli
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name 'hoge'
OK
127.0.0.1:6379> get name
"hoge"
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> keys *
(empty list or set)
这里是Redis命令列表。
尝试使用Rails.cache进行缓存
终于可以尝试使用Rails来进行缓存了。
在这里我们将使用以下命令。
Rails.cache.write(key, value) : キャッシュデータを保存
Rails.cache.exist?(key) : key を持つキャッシュデータがあるか確認
Rails.application.routes.draw do
get 'hoge/:id', to: 'redis_samples#hoge'
end
class RedisSamplesController < ApplicationController
def hoge
Rails.cache.write('name', 'hogehoge') if params[:id].to_i > 0
render json: Rails.cache.exist?('name')
end
end
我会从控制台调用API。
一开始,将参数设置为 id = 1,以保存缓存数据。
当然会返回true。
$ curl localhost:3001/hoge/1
true
当我从Redis容器中查看缓存存储时,我可以确认之前保存的缓存数据已经被保存了!同时,可以使用ttl命令以秒为单位获取缓存数据的剩余有效期。
$ docker exec -it myapp_redis_1 /bin/bash
root@05aaca0b40db:/data# redis-cli
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"\x04\bo: ActiveSupport::Cache::Entry\t:\x0b@valueI\..."
127.0.0.1:6379> ttl name
(integer) 49
只要在指定的有效期限过后执行,就可以确认缓存数据已被正确删除。
127.0.0.1:6379> keys *
(empty list or set)
让我们从Rails端确认最后是否已被删除。
当使用参数 id = 0 调用API时,将返回 false。
$ curl localhost:3001/katagamis/hoge/0
false
结束
我本以为这件事很快就能做完,结果却花了挺多时间,所以在还没忘记的时候,我记下来了备忘录。
这并不是一篇完整的教程文章,只是作为在开发过程中的参考,希望能有所帮助。
如果有意见、问题等,请随时提出!
请参考这篇文章。
-
- https://morizyun.github.io/ruby/rails-function-cache-fetch-write-delete.html
-
- https://qiita.com/yamashun/items/bf9a3d29de749cf18f2e
-
- https://qiita.com/pokohide/items/7397b92a188da841b435
- https://www.sejuku.net/blog/58218