Quantcast
Channel: Ruby on Railsの記事一覧|TechRacho by BPS株式会社
Viewing all articles
Browse latest Browse all 1406

Solid Cable README: DBベースのAction Cableアダプタ(翻訳)

$
0
0

概要

MITライセンスに基づいて翻訳・公開いたします。

Solid Cable README: DBベースのAction Cableアダプタ(翻訳)

Solid Cableは、データベースを用いるAction Cableアダプタです。メッセージをデータベースのテーブルに保存して、更新があるかどうかを定期的にポーリングします。
これにより、それ以外の目的でRedisが不要な場合に、Redisへの一般的な依存を削除できます。Action Cableの機能でRedisが必須でなくなれば、Railsアプリをデプロイしやすくなります。

Solid Cableは、MySQL、SQLite、PostgreSQLで動作することがテストされています。

Action Cableには既に専用のPostgreSQLアダプタが存在しており、組み込みのNOTIFYコマンドでパフォーマンスを強化しています。ただし、このアダプタにはペイロードが8KBまでという制限があります。ブロードキャストするペイロードが大きい場合や、NOTIFYコマンドを使いたくない場合は、Solid Cableが最適な代替手段となります。

🔗 インストール

新しいRails 8では、Solid Cableがデフォルトで設定されます。以前のバージョンのRailsを使っている場合は、以下の手順に沿って手動でSolid Cableを追加できます。

  1. bundle add solid_cable
  2. bin/rails solid_cable:install

上を実行すると、config/cable.ymlを上書きしてdb/cable_schema.rbを作成し、Solid Cableがproduction向けのケーブルアダプタとして使われるようになります。

次に、ケーブルデータベースの設定をconfig/database.ymlに追加する必要があります。SQLiteを使っている場合は、以下のように設定します。

production:
  primary:
    <<: *default
    database: storage/production.sqlite3
  cable:
    <<: *default
    database: storage/production_cable.sqlite3
    migrations_paths: db/cable_migrate

MySQL/PostgreSQL/Trilogyを使っている場合は、以下のように設定します。

production:
  primary: &primary_production
    <<: *default
    database: app_production
    username: app
    password: <%= ENV["APP_DATABASE_PASSWORD"] %>
  cable:
    <<: *primary_production
    database: app_production_cable
    migrations_paths: db/cable_migrate

config/cable.ymlファイルは、bin/rails solid_cable:installを呼び出せば自動的にセットアップされるので、設定の追加は不要です(ただし、 database.yml内のcable名が一致するようにしておかなければなりません)。

ただし、Solid Cableを別の環境(staging環境やdevelopment環境など)で利用したい場合は、config/cable.ymlファイル内で対応する環境に手動でconnects_toブロックを追加しなければなりません。この場合も同様に、 config/cable.ymlで使われるデータベース名がconfig/database.ymlで定義されているデータベース名と一致させること。

続いて、production環境で db:prepareを実行して、データベースを作成してスキーマが読み込まれるようにします。

🔗 単一データベースでの利用について

Solid Cableは、別のデータベースで実行することが推奨されますが、単一のデータベースをアプリとAction Cableで兼用することも可能です。

  1. db/cable_schema.rbの内容を通常のマイグレーションにコピーしてから、db/cable_schema.rbを削除する
  2. config/cable.ymlに記載されているconnects_toブロックを削除する
  3. bin/rails db:migrateを実行する

この場合はマルチデータベースではないので、database.ymlにprimaryデータベースとcableデータベースを持つ必要はありません。

🔗 設定方法

Solid Cableのすべての設定は、config/cable.ymlファイルで管理されます。デフォルトでは以下のように設定されます。

production:
  adapter: solid_cable
  connects_to:
    database:
      writing: cable
  polling_interval: 0.1.seconds
  message_retention: 1.day

利用可能なオプションは以下のとおりです。

connects_to
Active Recordで使うデータベースをSolid Cableモデル用に設定します。ここでは、Active Recordで利用可能な全オプションを利用できます。
polling_interval
ポーリング間隔の頻度を設定します(デフォルトは0.1秒)。
message_retention
メッセージをデータベースに保持する期間を設定します。メッセージのトリミングを実行するときのカットオフ値として使われます(デフォルトは1日)。
autotrim
Solid Cableでメッセージの自動トリミングを有効にするかどうかを設定します(デフォルトはtrue)。
silence_polling
ポーリング時のActive Recordログ出力を抑制するかどうかを指定します(デフォルトはtrue)。
use_skip_locked
トリミング実行中にFOR UPDATE SKIP LOCKEDを使うかどうかを指定します(デフォルトはtrue)。これは今後自動検出されるようになる予定ですが、現時点では、この機能をサポートしていないデータベース(MySQL < 8、PostgreSQL < 9.5)を使う場合はfalseを指定する必要があります。SQLiteはシーケンシャル書き込みなので影響しません。
trim_batch_size
古いレコードを削除するときのバッチサイズを指定します(デフォルトは100)。

🔗 メッセージのトリミング機能

Solid Cableのメッセージは、message_retention設定(メッセージを保持する期間を決定する)に基づいて自動トリミング(削除)されます。message_retentionが指定されていない場合や、設定の解析に失敗した場合は、デフォルトの1.dayが設定されます。メッセージがブロードキャストされると、メッセージがトリミングされます。

自動トリミングは、ブロードキャスト時に削除を実行する可能性があるため、負荷によってはパフォーマンスに悪影響が生じることもあります。必要であれば、autotrim: falseで自動トリミングを無効にして、後でトリミング用のジョブ(SolidCable::TrimJob.perform_later)を手動でエンキューすることも、負荷の小さい時間帯に定期実行することも可能です。

🔗 アップグレードについて

Solid Cableバージョン3未満を既にインストールしていて、Solid Cable 3にアップグレードする場合は、solid_cable:updateを実行して新しいマイグレーションをインストールしてください。

🔗 ベンチマーク

Solid Cableのbench/ディレクトリには、ベンチマーク用の最小限のRailsアプリが置かれています。
このアプリを独自サーバーにデプロイしてベンチマークを実行したい場合は、config/deploy.ymlファイルを更新して独自サーバーを指すようにしてください。

ベンチマークにはk6を使っています。セットアップのほとんどは以下の記事から取得しています。

参考: Real-time stress: AnyCable, k6, WebSockets, and Yabeda—Martian Chronicles, Evil Martians’ team blog

  1. k6をインストールする
  2. xk6 build --with
    github.com/anycable/xk6-cable
    を実行してxk6-cableをインストールする。
    これにより、k6のカスタムバイナリが出力されます。
  3. ./k6 run loadtest.jsを実行して負荷テストを行います。
    • このスクリプトにはさまざまな環境変数を渡せます。
      • WS_URL: Websocketコネクションの送信先URL
      • MAX: サーバーにアクセスする仮想ユーザー数
      • TIME: 負荷テストの実行期間
      • MESSAGES_NUM: 個別のVU(virtual users)がサーバーに送信するメッセージの件数

🔗 結果

以下の負荷テストはHetzner CCX13で実行され、MESSAGES_NUMには5、TIMEには90を指定しました。

🔗 SQLite
  • ポーリング間隔: 0.1秒
  • 自動トリミング: オン

100 VUの場合:

rtt..................: avg=135.82ms min=50ms     med=138ms    max=357ms    p(90)=174ms    p(95)=195ms
ws_connecting........: avg=205.81ms min=149.35ms med=199.01ms max=509.48ms p(90)=254.04ms p(95)=261.77ms

250 VUの場合:

rtt..................: avg=146.24ms min=50ms     med=144ms    max=435ms p(90)=209ms   p(95)=234.04ms
ws_connecting........: avg=222.15ms min=146.47ms med=208.57ms max=1.3s  p(90)=263.6ms p(95)=284.18ms

500 VUの場合:

rtt..................: avg=271.79ms min=48ms     med=205ms    max=1.15s p(90)=558ms    p(95)=660ms
ws_connecting........: avg=248.81ms min=145.89ms med=221.89ms max=1.38s p(90)=290.41ms p(95)=322.2ms

750 VUの場合:

rtt..................: avg=548.27ms min=51ms     med=438ms    max=5.19s  p(90)=1.18s  p(95)=1.29s
ws_connecting........: avg=266.37ms min=144.06ms med=224.93ms max=2.33s  p(90)=298ms  p(95)=342.87ms
  • 自動トリミング: オフ

250 VUの場合:

rtt..................: avg=139.47ms min=48ms     med=142ms    max=807ms p(90)=189ms    p(95)=214ms
ws_connecting........: avg=212.58ms min=146.19ms med=196.25ms max=1.25s p(90)=255.74ms p(95)=272.44ms
  • ポーリング間隔: 0.01秒(Radisに匹敵する値)

250 VUの場合:

rtt..................: avg=84.22ms  min=43ms     med=69ms     max=416ms p(90)=137ms    p(95)=150ms
ws_connecting........: avg=219.37ms min=144.71ms med=200.77ms max=2.17s p(90)=265.23ms p(95)=290.83ms
🔗 Redis
  • インスタンス: 同じマシン上にホスティング

100 VUの場合:

rtt..................: avg=68.95ms  min=41ms     med=56ms     max=6.23s  p(90)=114ms   p(95)=129ms
ws_connecting........: avg=211.09ms min=153.23ms med=195.69ms max=1.44s  p(90)=258.1ms p(95)=272.23ms

250 VUの場合:

rtt..................: avg=69.32ms  min=40ms     med=56ms     max=645ms p(90)=119ms    p(95)=135ms
ws_connecting........: avg=212.95ms min=142.92ms med=196.31ms max=1.25s p(90)=260.25ms p(95)=273.49ms

500 VUの場合:

rtt..................: avg=87.5ms   min=40ms     med=67ms     max=839ms p(90)=149ms    p(95)=176ms
ws_connecting........: avg=242.62ms min=142.03ms med=213.76ms max=2.34s p(90)=291.25ms p(95)=324.04ms

750 VUの場合:

rtt..................: avg=162.54ms min=39ms  med=123ms    max=2.26s p(90)=343.1ms  p(95)=438ms
ws_connecting........: avg=353.08ms min=143ms med=264.15ms max=2.73s p(90)=541.36ms p(95)=1.15s
🔗 MySQL
  • ポーリング間隔: 0.1秒
  • 自動トリミング: オン
  • インスタンス: 同じマシン上にホスティング

100 VUの場合:

rtt..................: avg=136.02ms min=51ms     med=137ms    max=877ms p(90)=168.1ms  p(95)=198ms
ws_connecting........: avg=207.76ms min=151.93ms med=196.74ms max=1.21s p(90)=249.91ms p(95)=260.37ms

250 VUの場合:

rtt..................: avg=159.33ms min=51ms    med=149ms    max=559ms p(90)=236ms    p(95)=263ms
ws_connecting........: avg=232.38ms min=151.6ms med=218.09ms max=1.38s p(90)=287.99ms p(95)=324.6ms

500 VUの場合:

rtt..................: avg=441.07ms min=51ms     med=312ms    max=2.29s  p(90)=931ms    p(95)=1.07s
ws_connecting........: avg=256.73ms min=152.23ms med=231.02ms max=2.31s  p(90)=305.69ms p(95)=340.83ms

750 VUの場合:

rtt..................: avg=822.08ms min=51ms     med=732ms    max=5.05s  p(90)=1.76s    p(95)=1.97s
ws_connecting........: avg=278.08ms min=146.66ms med=236.35ms max=2.37s  p(90)=318.17ms p(95)=374.98ms
🔗 PostgreSQLをSolid Cableと併用した場合
  • ポーリング間隔: 0.1秒
  • 自動トリミング: オン
  • インスタンス: 同じマシン上にホスティング

100 VUの場合:

rtt..................: avg=137.45ms min=48ms     med=139ms    max=439ms    p(90)=179.1ms  p(95)=204ms
ws_connecting........: avg=207.13ms min=150.29ms med=197.76ms max=443.67ms p(90)=254.44ms p(95)=263.29ms

250 VUの場合:

rtt..................: avg=151.63ms min=49ms     med=146ms    max=538ms p(90)=222ms    p(95)=248.04ms
ws_connecting........: avg=245.89ms min=147.18ms med=205.57ms max=30s   p(90)=265.08ms p(95)=281.15ms

500 VUの場合:

rtt..................: avg=362.79ms min=50ms     med=249ms    max=1.21s p(90)=757ms    p(95)=844ms
ws_connecting........: avg=257.02ms min=146.13ms med=227.65ms max=2.39s p(90)=303.22ms p(95)=344.39ms
🔗 PostgreSQLを専用アダプタで使った場合

100 VUの場合:

rtt..................: avg=69.76ms  min=41ms     med=57ms     max=622ms p(90)=116ms    p(95)=133ms
ws_connecting........: avg=210.97ms min=149.68ms med=196.06ms max=1.27s p(90)=259.67ms p(95)=273.17ms

250 VUの場合:

rtt..................: avg=73.43ms  min=40ms     med=58ms     max=698ms p(90)=126ms    p(95)=141ms
ws_connecting........: avg=210.83ms min=143.01ms med=195.22ms max=1.27s p(90)=259.27ms p(95)=272.6ms

🔗 ライセンス

このgemは、MITライセンスの条項の下でオープンソースとして利用可能です。

関連記事

Solid Cache README: DBベースのキャッシュストア(翻訳)

Solid Queue README -- DBベースのActive Jobバックエンド(翻訳)

The post Solid Cable README: DBベースのAction Cableアダプタ(翻訳) first appeared on TechRacho.


Viewing all articles
Browse latest Browse all 1406

Latest Images

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

Trending Articles



Latest Images

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭

赤坂中華 わんたん亭