Docker で Redis + Sidekiq を実装する

プログラミング

 

現場で Sidekiq を扱う事になったので、Docker での環境構築と、簡単な使い方を記録します。

Sidekiq とは

Sidekiq は Rails で非同期処理を簡単に行えるようにするための gem です。

Sidekiq

使用場面としては以下が考えられます。

  • メール通知
  • API を叩いて大量のデータを取得

実装

Dockerfile

                    

FROM ruby:2.7.1
RUN curl -sS https://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 -qq \
    && apt-get install -y nodejs yarn chromium-driver shared-mime-info\
    && yarn add chartkick chart.js jquery\
    && mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.yml

Sidekiq は Redis で動かす必要があるため、その設定を行います。

                    

version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
    stdin_open: true
    tty: true
  chrome:
    image: selenium/standalone-chrome:3.141.59-dubnium
    ports:
      - 4444:4444
  redis:
    image: redis:6.0.9
    env_file: .env
    command: redis-server --appendonly yes
    ports:
      - 6379:6379

volumes:
  mysql-data:
    driver: local

Redis についてはこちらが参考になりました。

【入門】Redis - Qiita
背景現在、自社サービスでRedisを利用していることもあり、あらためて勉強、まとめてみました。今回は、Redisの概要・特徴・設定・レプリケーションの基礎的な部分を記載しています。※間違…

Sidekiq をインストール

                    

gem 'sidekiq'
gem 'sinatra', require: false

bundle install をしてください。

sinatra はダッシュボードを使用するためにインストールします。

Sidekiq 起動時の設定

config/sidekiq.yml

                    

:verbose: false
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 10
:queues:
  - default
  - test

config/redis.yml

                    

default: &default
  db:
    sidekiq: 0
    # cache:   1
    # session: 2

development:
  <<: *default
  host: redis

test:
  <<: *default
  host: redis

config/initializers/sidekiq.rb

                    

redis_config = YAML.load_file('config/redis.yml')[Rails.env]
redis_config['db'] = redis_config['db']['sidekiq']

Sidekiq.configure_server do |config|
  config.redis = {
    url: "redis://#{redis_config['host']}/#{redis_config['db']}"
  }
end

Sidekiq.configure_client do |config|
  config.redis = {
    url: "redis://#{redis_config['host']}/#{redis_config['db']}"
  }
end

 

routes.rb

                    

Rails.application.routes.draw do
  # この2行を追記
  require 'sidekiq/web'
  mount Sidekiq::Web, at: "/sidekiq"
end

アプリケーションを作成

今回はボタンを押したら非同期処理が開始され、元のページにリダイレクトするといった処理を作成していきます。

views/sidekiq_sample/index.html.rb

まずはボタンの作成。

今回は非同期処理を行うジョブに GreetWorker と名付けました。

                    

<%= button_to "GreetWorker を実行", sidekiq_sample_index_path, {method: :post}%>

作成されたボタンはこんな感じ。

controllers/sidekiq_sample_controller.rb

ボタンを押したら create アクションが実行されます。

GreetWorker を30秒後に実行し、引数として”GreetWorker 実行”を渡しています。

                    

class SidekiqSampleController < ApplicationController
  def index
  end

  def create
    GreetWorker.perform_in(30.seconds, "GreetWorker 実行!!!")
    render template: "sidekiq_sample/index"
  end
end

 

workers/greet_worker.rb

非同期処理の中身を書いていきましょう。

この非同期処理を行うファイルを Worker と呼び、処理自体のことをジョブと呼びます。

                    

class GreetWorker < ApplicationController
  include Sidekiq::Worker
  sidekiq_options queue: :test, retry: 5

  def perform(string)
    p "#{string}"
  end
end

オプションとして queue, retry を指定しています

  • queue … Worker が利用するキューの名前を指定します。デフォルトの値は default
  • retry … ジョブが失敗したときに再度行うかを指定します。デフォルトは true ですが、真偽値でなく、回数を指定することも出来ます。

ボタンを3回押してみる

http://localhost:3000/sidekiq/scheduledにアクセス

「予定」のところにジョブが積まれているのがわかります。

Sidekiq を起動していないので、このままでは実行されません。

ちなみに rails console からも確認することが出来ます。

                    

> Sidekiq::ScheduledSet.new.size
=> 3

Sidekiq の API 

Sidekiq を起動

                    

$ docker compose exec web bundle exec sidekiq -C config/sidekiq.yml

ターミナルに出力されているのが確認出来ました。

                    

2021-09-27T23:57:35.969Z pid=58 tid=40u INFO: Booting Sidekiq 6.2.2 with redis options {:url=>"redis://redis/0"}


               m,
               `$b
          .ss,  $$:         .,d$
          `$$P,d$P'    .,md$P"'
           ,$$$$$b/md$$$P^'
         .d$$$$$$/$$$P'
         $$^' `"/$$$'       ____  _     _      _    _
         $:     ,$$:       / ___|(_) __| | ___| | _(_) __ _
         `b     :$$        \___ \| |/ _` |/ _ \ |/ / |/ _` |
                $$:         ___) | | (_| |  __/   <| | (_| |
                $$         |____/|_|\__,_|\___|_|\_\_|\__, |
              .d$$                                       |_|
      

2021-09-27T23:57:36.160Z pid=58 tid=40u INFO: Booted Rails 6.1.4.1 application in development environment
2021-09-27T23:57:36.162Z pid=58 tid=40u INFO: Running in ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
2021-09-27T23:57:36.162Z pid=58 tid=40u INFO: See LICENSE and the LGPL-3.0 for licensing details.
2021-09-27T23:57:36.163Z pid=58 tid=40u INFO: Upgrade to Sidekiq Pro for more features and support: https://sidekiq.org
2021-09-27T23:57:36.172Z pid=58 tid=40u INFO: Starting processing, hit Ctrl-C to stop
2021-09-27T23:57:47.102Z pid=58 tid=cea class=GreetWorker jid=716dd299cef1b681f1a8def5 INFO: start
2021-09-27T23:57:47.245Z pid=58 tid=cj6 class=GreetWorker jid=b813cb60a7ccb23b288cbfa2 INFO: start
2021-09-27T23:57:47.343Z pid=58 tid=ciu class=GreetWorker jid=b91a4066da66578cb7537974 INFO: start
"GreetWorker 実行!!!"
"GreetWorker 実行!!!"
2021-09-27T23:57:47.675Z pid=58 tid=cj6 class=GreetWorker jid=b813cb60a7ccb23b288cbfa2 elapsed=0.426 INFO: done
2021-09-27T23:57:47.675Z pid=58 tid=ciu class=GreetWorker jid=b91a4066da66578cb7537974 elapsed=0.332 INFO: done
"GreetWorker 実行!!!"
2021-09-27T23:57:47.676Z pid=58 tid=cea class=GreetWorker jid=716dd299cef1b681f1a8def5 elapsed=0.574 INFO: done

 

その他の参考記事

Railsで非同期処理を行える「Sidekiq」 - Qiita
Sidekiqとは?Sidekiqは、resqueやdelayed_jobなどのような非同期処理を行いたい時に使うライブラリです。複数のジョブを同時に実行することにより、メモリを節約すること可能で…

 

 

 

コメント