×
Copy
Open
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Railsで⾮同期処理 Sidekiqを使うための準備と 使ってみて気づいたこと @wtnabe Kanazawa.rb meetup 36 2015-08-29 (Sat) at IT-Plaza MUSASHI
Slide 2
Slide 2 text
お品書き ⾮同期処理とは Sidekiq ⾮同期Worker作成時の注意 課題はテスト
Slide 3
Slide 3 text
⾮同期処理とは
Slide 4
Slide 4 text
Railsで⾮同期処理とは HTTP requestと同期しないもの ジョブの実⾏指定と実際の実⾏時間が同 期しないもの 伝統的なバッチジョブは違う? クライアントサイドの⾮同期処理とは意味が違う
Slide 5
Slide 5 text
例えば POST時の処理を後回しに メールの送信 画像のサムネイル⽣成 response time短縮向け ⼤量の作業をスケジュール実⾏
Slide 6
Slide 6 text
⾮同期⽤のGem Rails 4.2+ ActiveJob ( adaptor ) Rails 4.1- (various methods) DelayedJob BackgrounDrb Rescue Sidekiq
Slide 7
Slide 7 text
Sidekiq
Slide 8
Slide 8 text
Sidekiqの特徴 http://sidekiq.org/ Queue ⽤のストレージは Redis Celluloid を使ったスレッドモデル Sinatra 製の Dashboard 付き Sidekiq Pro アリ
Slide 9
Slide 9 text
今回選んだ理由 もともとよく名前を⽬にしていた redis 環境の⽤意が楽になっていた Sidekiq Pro があるってことはビジネスを 起こせるレベルのツールと看做せる Dashboard がレポートとしても使えそう
Slide 10
Slide 10 text
セットアップ bundle install Procfile initializers/sidekiq.rb config/sidekiq.yml config/routes.rb ( if you wish Dashboard )
Slide 11
Slide 11 text
Redisのインストールは省略
Slide 12
Slide 12 text
bundle install in Gemfile gem 'sidekiq'
Slide 13
Slide 13 text
Foremanの話はこちら 前回 meetup #35 で紹介済み Lightweight PHP development environment with Foreman and built-in server // Speaker Deck
Slide 14
Slide 14 text
Procfile Sidekiq⽤に別なRailsを⽴ち上げるイメージ web: bundle exec rails s redis: redis-server worker: mkdir -p tmp/pids && \ bundle exec sidekiq \ -C config/sidekiq.yml Unicornと同じように全部bundle execで済んじゃう
Slide 15
Slide 15 text
Herokuでは初期化に注意 RailsのバージョンによってDATABASE接 続の設定反映の挙動が違う Herokuは環境変数設定を推奨している が、特にその辺りが違う see Advanced Options · mperham/sidekiq Wiki
Slide 16
Slide 16 text
Concurrencyに注意 RailsのDB connection poolはdefault 5 Sidekiqのconcurrencyはdefault 25 溢れるに決まってる><
Slide 17
Slide 17 text
sidekiq.ymlの例 :concurrency: 3 :staging: :concurrency: 9 :production: :concurrency: 9 development は SQLite, production と staging で web と worker 2つの サーバから max 20 conn までの DB サーバに繋ぐ想定
Slide 18
Slide 18 text
Dashboard in Gemfile gem 'sinatra' in routes.rb require 'sidekiq/web' mount Sidekiq::Web => '/sidekiq' もちろんアクセス制限は忘れないで><
Slide 19
Slide 19 text
Sidekiq Dashboard Demo
Slide 20
Slide 20 text
Workerの作り⽅
Slide 21
Slide 21 text
in Gemfile gem 'sidekiq'
Slide 22
Slide 22 text
in application.rb app/workers ディレクトリを 作る autoload 対象に eager_load 対象に eager_load については ggl `rails thread'
Slide 23
Slide 23 text
in foo_worker.rb class FooWorker include Sidekiq::Worker def perform(*args) end end
Slide 24
Slide 24 text
How to use FooWorker.perform_async(arg1, ...) FooWorker.perform_in(time, arg1, ...) etc
Slide 25
Slide 25 text
worker⽤のRails上で perform()が呼ばれる request を受けた Rails とは別な⼈であることに注意 perform_in() を使うと遅延時間が指定できる
Slide 26
Slide 26 text
Worker作成時の注意点
Slide 27
Slide 27 text
基本⽤語 ここでは以下のように⾔葉を⽤いる Worker 実際に⾮同期の動作を担当するclass ジョブ Workerが実⾏する⼀つ⼀つの処理
Slide 28
Slide 28 text
注意点 perform() にはプリミティブを与える できるだけ細かくジョブを分ける ※ Rubyにはプリミティブなんて存在しないけど
Slide 29
Slide 29 text
serializeしたオブジェクト じゃダメなの?
Slide 30
Slide 30 text
オブジェクト渡し 簡単だしDBに負担掛けない Queueの容量膨らむ 安定してdeserializeできるとは限らない 処理の記録の意味が分からない
Slide 31
Slide 31 text
処理の記録重要 ⾮同期処理はいつ終わるか分からない 「ポチッとやって結果を⽬視」みたいな やり⽅は通⽤しない
Slide 32
Slide 32 text
Sidekiqの記録 Workerの名前と引数がそのまま残る readableな名前と引数を使う
Slide 33
Slide 33 text
class BulkThumbnailGeneratorWorker include Sidekiq::Worker def perform(k, id, attr, size) r = Object.const_get(k).find(id) ... end end 例えば⼀括サムネイル⽣成
Slide 34
Slide 34 text
こうすると どのModelの どのIDの どのカラムの画像を どのサイズにするのか これらが記録に残る。readableで丸分かり。
Slide 35
Slide 35 text
しかも ⼩分けにできる
Slide 36
Slide 36 text
ジョブの⼩分け重要 × 1万回のeachのある1つのジョブ ○ 1万のジョブ ※ ⼩分けなら記録も明確で途中からretryできる
Slide 37
Slide 37 text
ジョブの分け⽅ ⼤量の作業が必要な場合 peform の中で each しない each の中で perform_in を呼ぶ 処理に掛かる時間を予測して遅延時間 を指定しておく もちろん必要な遅延時間はあらかじめ予測して検証する
Slide 38
Slide 38 text
課題はテスト
Slide 39
Slide 39 text
今のところ⾃動テストなし そんなに変更しない いつも⾛らせる必要はない
Slide 40
Slide 40 text
⼤きな課題は peform の呼び⽅呼ばれ⽅のコードというよりは 遅延時間やジョブの衝突などの⽅で、こ れは⾮常にテストしにくい
Slide 41
Slide 41 text
(機会があれば) 頑張ります><