MisskeyIO / misskey

🌎 A federated blogging platform 🚀

Home Page:https://misskey.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BullMQをやめる

u1-liquid opened this issue · comments

もっと正確には、Redisベースのキューをやめる
(負荷に耐えられないので)

前提

  • HA構成が可能であること(もしくはサーバーレスであること)
  • 別途のライセンス費用が発生しないこと

  • BullMQを使い続ける
  • RabbitMQ
  • ActiveMQ
  • Kafka
  • ZeroMQ

とても個人的な観点のPros & Cons

BullMQを使い続ける

この場合、既存のSingle-Node RedisではなくCluster構成に対応させることにする

Pros

  • ソースコードの変更が一番少ない

Cons

  • Clusterを組まなければならない
  • 何も解決されない可能性がある

RabbitMQ

Pros

  • 多方面から実績のあるソリューション
  • 公式のマネージメントUIがある

Cons

  • AMQPなのでクライアントはAMQPライブラリを使えばいいとされているが、node.js用はやや開発が途切れている感がある
  • 偶数個のサーバーで運用する必要がある

ActiveMQ

Pros

  • 専用のnode.js向けクライアントライブラリがある
  • 比較的機能が多いとされている(要確認)
  • 公式のWeb Console UIがある

Cons

  • HA構成にはZookeeperがいる
  • 最近も採用されているかと言うと微妙

Kafka

Pros

  • 多方面から実績のあるソリューション
  • TPSがとても高い

Cons

  • 管理コストも高い
  • cliで管理するのがほぼ常識みたいな感じ
  • 公式のWeb UIが無い(OSSはある)

ZeroMQ

Pros

  • リクエストをすぐ処理することに向いてる気がする
  • ブローカーを必要としない実装なので追加で管理するサーバーが増えない

Cons

  • メッセージを処理予定だったサーバーが勝手に消える可能性があるという今のioの構造には向かないかも
  • ブローカーがないので総計を取るには工夫が必要

RabbitMQ良さそう

RabbitMQで進めることにして、node.jsライブラリとしてはrascalを採用して実装中

実装の方針

  • 基本的に全てのオプションを設定ファイルで触れるようにする
  • 実装には1つのvhostを、rascalの設定でnamespaceで分けて、queueごとにvhost設定を作くる(rabbitmqサーバー側の設定はだるそう)
  • 基本的にrascalのexampleにあるadvanced構成を真似る
  • quorum queueを設定するが、これによるリトライは基本的にプロセスが落ちた時(デフォルトで15分のackタイムアウト)にのみ適用する(コード上では参照しない)
  • クライアントが勝手に死んだときジョブが消える可能性があるためrascalのリトライ機能は使わない、エラーが起きたらdelayキューにメッセージごとのTTLを設定してDLXフローを使う
    ↑ドキュメント読み間違えた基本的にはrascalのリトライ機能を使ってよさそう
  • inboxとdeliverはretry回数に合わせて1m,3m,5m,10m,30m,1h,2h,4h,8hのbackoffをさせる、ほかは固定で1mのdelayでよさそう
  • misskeyにdashboardは実装しない
  • statsはqueueのassertの返り値で表現できそう
  • ジョブのリトライ機能も一応実装する
  • 溜まったDLQのTTLは14日くらい?
  • vhostのconcurrencyは同時に実行可能なジョブの数ではないので注意
    同時に実行するジョブの設定はsubscriptionsのprefetchの数

BullMQが重い理由引用

ジョブキューの時間計算量が実行中(待機中ではない)のジョブの数に比例するという性能特性があり、かつ時間計算量がタイムアウトの閾値を超えるとジョブの完了処理がコケるようになり、原理的に2度と状況が改善方向に向かうことはないという性能劣化の正帰還ができあがっていた(ので、全部一度引っこ抜いて待機列に詰め直した) https://misskey.io/notes/9o4bl4yw9bpv0djx

具体的にはこの一行の時間計算量が active リスト(実行中のジョブリスト)の要素数に比例してます。完了したジョブをリストから取り除く処理なんだけれど、増えた待機ジョブに対応してワーカーを増やしまくるなどして実行中のジョブがひとたび急増すると、ここの処理が激重になり、タイムアウトするようになり、つまりジョブは2度と完了せず、不幸が訪れる。ジョブに増加に対応しようとして逆に首が締まる最悪のループに入るわけです。 https://misskey.io/notes/9o4c09uu3gov0eia

結論としては詰め直せばええ https://misskey.io/notes/9o4bn9k6vhcm0ddf