はじめに
業務のなかでRails + Redis + Sidekiqを使った非同期処理について触ったので学んだことを備忘録として残しました。
誰かの参考になれば幸いです。
もし間違いなどがありましたら、教えていただると大変ありがたいです!!よろしくお願いいたします🙇♂
非同期処理とは
非同期処理とは、プログラムの実行においてタスクの完了を待たずに次の処理に進む手法のこと。一般的に、非同期処理は特定のタスクやジョブを別のスレッドやプロセスでバックグラウンドで実行することを指す。
オンライン処理・バッチ処理・非同期処理の違いについて
オンライン処理について
- オンライン処理は、即時処理とも呼ばれ、ユーザーからの要求に対して即座に処理結果を返す方式。
- ユーザーは処理の完了を待ち、リアルタイムに反応を得ることを期待します。そのため、短い処理時間が要求される。
バッチ処理について
- バッチ処理は、一括処理とも呼ばれ、ある程度の量のデータをまとめて処理する方式。
- バッチ処理は時間のかかる処理を行うことができ、数分から数時間、場合によってはそれ以上の時間を要することがある。
非同期処理について
- ユーザーは処理の完了を待たずに操作することが出来て、オンライン処理的。サーバー側にとっては呼び出された別リクエストは裏でバッチ的に処理されるので、両方のいいとこ取りとも言えます。
- 例外処理を考え始めると途端に考えることが増える。
Railsで非同期処理を実行するフレームワークがActive Job
active jobとは
- ジョブを宣言し、それによってバックエンドでさまざまな方法によるキュー操作を実行するためのフレームワーク
jobとqueue
名称 | 読み方 | 概要 |
---|---|---|
job | ジョブ | コンピューターがする仕事の単位 |
Queue | キュー | データ構造の一つ。待ち行列 |
ジョブは現実世界で例えるなら、
- 会社に行く
- 会社から帰る
- お風呂に入る
- 料理を作る
- 寝る
と言ったような一つ一つのタスクのようなもの。
キューはタスクを登録するための入れ物とするイメージ。
キューの特徴としては先に登録されたものから先に実行する。
※ActiveJobでは複数のキューを優先順位をつけて実行することも出来るみたいです
登録順 | タスク内容 |
---|---|
1 | 会社に行く |
2 | 会社から帰る |
3 | お風呂に入る |
4 | 料理を作る |
5 | 寝る |
このようなジョブを1から順番にキューに登録、実行した場合、1会社に行く->2会社から帰る->3お風呂に入る->4料理をつくる->寝るの順で実行される。
ActiveJobはこれらの処理をバックグラウンドで実行することができる機能のことをいう。
ActiveJobを使う場面
先述したようにActiveJobはバックグラウンドで実行ができるため、処理をアプリケーションの裏側で実行させることができる。
なので、ActiveJobは基本的にリアルタイム性を伴わない場合や重たい処理に使われることが多い。
メールの配信
画像の処理
データを集計後にCSVファイルに変換
このような時間がかかる処理の場合には、先にレスポンスをクライアントへ返しておき、バックグラウンドで処理を別途実行する。
Rails自身が提供するのは、ジョブをメモリに保持するインプロセスのキューイングシステムだけで、 プロセスがクラッシュしたりコンピュータをリセットしたりすると、デフォルトの非同期バックエンドの振る舞いによって主要なジョブが失われてしまう。
そのため開発環境や、小規模アプリケーションの場合には、ActiveJobのみでも問題ないが、本番環境でアプリケーションを運用していくとなると、いろいろと不都合がでてくる。
上記のことから多くのproductionではActiveJobには非同期バックエンドなるサードパーティーのキューイングライブラリを決める必要がある。
sidekiqとは
- sidekiqはバックグラウンドジョブ処理を制御するためのキューイングライブラリ
- SidekiqはRuby(Rails)とは異なるプロセスで動かすソフトウェアで、何らかのバックグラウンドの処理を担当するもの。
Redisとは
- Redisとは、データをメモリ上に保存するタイプのインメモリ型のNoSQLでその中でもKVS(Key Value Store)と言われるもの。
- KVSとは、主としてキーとバリューのシンプルなデータを保存するタイプのデータベースのことで、RDB(Relational Database)のような複雑なデータは扱えない反面、高速に動作するという特徴がある。
そんな特徴から主な利用用途は、
- キャッシュ
- セッションデータ
- 大量のメール
などの一時的なデータの保存先としてとても有効
RailsサーバとRedisとSidekiqの関係
RailsサーバとRedisとSidekiqの関係を簡単に図で表すと上のようになる。
Railsサーバの処理の中で「後で処理するリスト」に任せたいJobがあれば、Redisの永続化しているキューにJobを追加(エンキュー)し、SidekiqがJobを取り出して(デキュー)実行していく。
ちなみに、これらのキュー操作を様々な方法で実行するためにインターフェースなどを定めてくれているフレームワークがActive Jobとなる。
通常のRailsの処理の流れ(オンライン処理)
- クライアントからHTTPリクエストがRailsサーバーに送られる
- 書類等の更新のリクエスト
- Railsがルーティングに従ってコントローラーとアクションを特定し、データベースに適切な処理を行う
- 書類等の更新、特定のcustomerへのメール送信
- RailsがビューをまとめてHTTPレスポンスとしてクライアントに返す
非同期のRailsの処理の流れ
- クライアントからHTTPリクエストがRailsサーバーに送られる
- 書類等の更新のリクエスト
- Railsがルーティングに従ってコントローラーとアクションを特定し、データベースに適切な処理を行う
- 書類等の更新、Jobのキュー登録(Enqueue)
- Railsが書類の更新をHTTPレスポンスとしてクライアントに返す
- 更新のレスポンスを返す。
- 一部時間のかかるJobはキュー登録されバックグラウンドで実行される
- 特定のcustomerへのメール送信
終わりに
今までなんとなくで理解していた非同期処理ですが、記事にすることで100%正しい表現が出来ているかはわかりませんが、自分の言葉で噛み砕くことが出来たのかなと思います。
今後も継続してアウトプットすることで理解を深めていけたらなと思います!!
参考サイト・書籍
https://railsguides.jp/active_job_basics.html
https://zenn.dev/yoiyoicho/articles/03863702867eb0
https://techracho.bpsinc.jp/hachi8833/2019_01_08/62705
https://qiita.com/petertakahashi/items/cb9ae73e5ba3020f4a89
https://dev.icare.jpn.com/dev_cat/sidekiq/
https://qiita.com/hirotakasasaki/items/9819a4e6e1f33f99213c
https://dev.classmethod.jp/articles/ruby-on-rails_active-job_queue_prioritize_carry_out/