将在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
广告
将在 10 秒后关闭
bannerAds