Sidekiqの高度なオプション [翻訳]

# Sidekiqの高度なオプション

最終更新 2019/09/03 編集者 Mike Perham

## Sidekiqの設定ファイル

Sidekiqの設定ファイルはYAML形式です。デフォルトの場所は `config/sidekiq.yml` になります。
高度なオプションを利用する場合のみ、設定ファイルを作る必要があります。高度なオプションとは、コンカレンシーサイズ、名前付きキュー、PIDファイルの場所指定などです。

設定ファイルの記載例は下記の通りです。

```yaml
:concurrency: 5
staging:
  :concurrency: 10
production:
  :concurrency: 20
:queues:
  - critical
  - default
  - low
```

設定ファイルの場所を明示的に指定する場合は `-C` フラグを使用してください。

```shell
sidekiq -C config/myapp_sidekiq.yml
```

コマンドラインで指定されたオプションは設定ファイルの内容を上書きします。

## キュー

デフォルトの状態では、Sidekiqは default と名前の付いた単一のキューのみを使用します。
複数のキューを利用したい場合は、`sidekiq` コマンドの引数として指定するか、[設定ファイル](https://github.com/mperham/sidekiq/blob/master/examples/config.yml)に記載することができます。
それぞれのキューには重みを設定することができます。重みとして 2 が設定されているキューは、1 が設定されているキューと比較して2倍の頻度でチェックされます。

引数でキューの名前と重みを指定する場合：

```shell
sidekiq -q critical,2 -q default
```

上記と同じ内容を設定ファイルで指定する場合：

```yaml
# ...
:queues:
  - [critical, 2]
  - default
```

常にキューを指定した順番通りに処理してほしい場合は、重みなしで処理してほしい順番通りに設定ファイルを記載してください。

引数で処理する順番通りにキューを指定する場合：

```shell
sidekiq -q critical -q default -q low
```

上記と同じ内容を設定ファイルで指定する場合：

```yaml
# ...
:queues:
  - critical
  - default
  - low
```

上記の通りに記載すると、defaultキューのジョブはcriticalキューが空の時のみ処理されます。

それぞれのキューのジョブをランダムな順番で処理してほしい場合は、重みを 1 に設定してください。そうすることでそれぞれのキューが均等に処理されるようになります。

```yaml
# ...
:queues:
  - ["foo", 1]
  - ["bar", 1]
  - ["xyzzy", 1]
```

ワーカーが使うキューはワーカークラスの中で指定することができます。

```ruby
class ImportantWorker
  include Sidekiq::Worker
  sidekiq_options queue: 'critical'

  def perform(*important_args)
    puts "Doing critical work"
  end
end
```

キューの数は少数にとどめてください。たくさんのキューはシステムをより複雑にしますし、[Sidekiq Proはポーリングなしで複数のキューを確実に処理することができません](https://github.com/antirez/redis/issues/1785)。
M個のSidekiq ProプロセスがN個のキューをポーリングする時、Redisに対してO（M*N）の操作が発生すること（これは非常に多い）を意味します。

SidekiqのWeb UIでは、もっとも新しく追加されたキュー（のジョブ）が一番上に表示されます。

### キューを予約しておく

特定のジョブだけを処理するキューをあらかじめ用意しておきたい場合、これをもっとも簡単に実現するには、異なるキューを処理する複数のSidekiqプロセスを実行してください。

```shell
sidekiq -q critical # criticalキューのジョブのみを処理する
sidekiq -q default -q low # それ以外のジョブを処理する
```

## ワーカー

Sideiqにはワーカーの振る舞いを制御するたくさんのオプションがあります。

- **queue** ワーカーが利用するキューの名前を指定する。デフォルトの値は *default*
- **retry** RetryJobsミドルウェアを有効にする。デフォルトの値は *true* 真偽値ではなく数字を与えると再試行する回数を指定することもできます。例：retry: 3
- **backtrace** 例外のバックトレースを保存しておくかどうか。保存されたバックトレースはWeb UIの再試行タブで見ることができます。真偽値または保存する行数を数字で指定することができます。デフォルトの値は *false* です。バックトレースはRedis上で非常に多くのスペースを使うため、再試行するジョブが多くなる場合は注意して扱ってください。
- **pool** Redisへジョブをプッシュする際に利用するコネクション数

```ruby
class HardWorker
  include Sidekiq::Worker
  sidekiq_options queue: :crawler, retry: false, backtrace: true

  def perform(name, count)
  end
end
```

デフォルトのオプションをワーカーに指定する場合は `Sidekiq.default_worker_options=` が利用できます。

```ruby
Sidekiq.default_worker_options = { 'backtrace' => true }
```

ワーカーに指定されたオプションはジョブのプッシュの際に上書きすることができます。

```ruby
HardWorker.set(queue: :critical).perform_async(name, count)
```

## 同時実行制御

Sidekiqプロセスの同時実行スレッド数を指定することができます。デフォルトでは、1つのSidekiqプロセスは**10個のスレッド** を作成します。
I/Oに関係するクラッシュが起きる場合は、この数字を減らすことができます。

```shell
bundle exec sidekiq -c 5
RAILS_MAX_THREADS=3 bundle exec sidekiq
```

コンカレンシーを50よりも大きくすることは非推奨です。Rails 5から、`RAILS_MAX_THREADS` でRailsとSidekiqのコンカレンシーを設定することができます。
ActiveRecordは `config/database.yml` でデータベースへ接続する際のコネクションプール数を指定することができます。この数はスレッド数と同じになるようにしてください。

## コネクションプール

Sidekiqは[connection_pool gem](https://github.com/mperham/connection_pool)を同封しており、ワーカーから利用することができます。
コネクションプールを利用することで、たくさんのスレッドが動く環境であっても、I/Oコネクションの数を制限することができるようになります。

```ruby
class HardWorker
  include Sidekiq::Worker

  MEMCACHED_POOL = ConnectionPool.new(size: 10, timeout: 3) { Dalli::Client.new }
  def perform(args)
    MEMCACHED_POOL.with do |dalli|
      dalli.set('foo', 'bar')
    end
  end
end
```

上記のようにすることで、このワーカーの同時実行数が多くなったとしても、Sidekiqプロセスからmemcachedへ接続するコネクション数を常に10個に限定することができます。