Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BullMQにしてからCPU使用率が高くなる、Deliver等のキューのWaitingが増えた #11000

Open
tamaina opened this issue Jun 12, 2023 · 45 comments
Labels
🔥high priority packages/backend Server side specific issue/PR 🐢Performance Efficiency related issue/PR

Comments

@tamaina
Copy link
Member

tamaina commented Jun 12, 2023

Summary

bullmqになってからjobConcurrencyの挙動が変わったらしく、deliverJobConcurrencyは128がデフォルトだとサーバーがハングしてしまうかもしれない

deliverJobConcurrencyを8とか16あたりにするべき

単純にキューの実行をする際にCPUリソースを食いまくるらしい

@tamaina tamaina added the ✨Feature This adds/improves/enhances a feature label Jun 12, 2023
@syuilo
Copy link
Member

syuilo commented Jun 13, 2023

@tamaina
Copy link
Member Author

tamaina commented Jun 13, 2023

(bullの実装が微妙だったのが治ったとかだと思ってた

@syuilo
Copy link
Member

syuilo commented Jun 13, 2023

明らかになんかおかしそう

@tamaina
Copy link
Member Author

tamaina commented Jun 13, 2023

個人的な感覚ではdeliverJobConcurrencyが128だったのがおかしいと思ってる

@syuilo
Copy link
Member

syuilo commented Jun 13, 2023

同じジョブでもBullMQにしてから負荷が高くなっていそうな雰囲気がある

@tamaina
Copy link
Member Author

tamaina commented Jun 13, 2023

単純に、ジョブ終了から次のジョブを呼び出すまでの時間が短縮されてジョブの実行数が増えたんだと思ってた

(キューメトリクスウィジェットでジョブが実行できた数は増えているように見える)

@tamaina
Copy link
Member Author

tamaina commented Jun 13, 2023

image

misskey.io死んだ?

@u1-liquid
Copy link
Sponsor Contributor

queueのratelimitの仕様も変わってこっちは結構上方修正してあげないと処理が止まっちゃうかも
deliverJobPerSecinboxJobPerSec などの設定、このlimitの適用範囲が完全にグローバルになってるので)

@SanMurakami
Copy link
Contributor

サーバー台数5倍ぐらいに増やしてやっとギリギリ捌けるって感じ
正直このままだと破産するのでなんとかして欲しい

@tamaina tamaina changed the title jobConcurrencyの値の挙動が変わったため、deliverJobConcurrencyのデフォルト値を下方修正するべきかも bullmqが重い Jun 14, 2023
@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

deliverJobConcurrencyを減らしてdeliverJobPerSecを増やすとかしてもダメな感じ?

@SanMurakami
Copy link
Contributor

deliverJobConcurrency減らすと捌ききれなくてどんどん溜まっていく
逆に増やすとCPU使用率がめっちゃ上がってサーバー台数がとんでも無いことになる
(通常5/24、現在24/24)

@tamaina tamaina changed the title bullmqが重い bullmqがCPUリソースを消費しまくる Jun 14, 2023
@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

(私はbullに戻す以外の選択肢を考えられない

@syuilo
Copy link
Member

syuilo commented Jun 14, 2023

BullMQのバグ?

@syuilo syuilo added 🐢Performance Efficiency related issue/PR packages/backend Server side specific issue/PR 🔥high priority and removed ✨Feature This adds/improves/enhances a feature labels Jun 14, 2023
@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

bullmqにした以外にキュー実行周りに手を加えていないならbullmqのせいなのでは

@syuilo
Copy link
Member

syuilo commented Jun 14, 2023

何か使い方間違ってるとかかも

@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

まあまずは使い方から疑うべき

@syuilo
Copy link
Member

syuilo commented Jun 14, 2023

@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

そんなに重たい処理には見えないというか、キュー実行に直接関係あるかしら(tickごとにCPU使用率が増えているわけではなさそうだし)

@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

まさかこれが重たいとか?

image

@u1-liquid
Copy link
Sponsor Contributor

これ結局nodeのシングルプロセス性能の問題と直結してるのでOut-Of-ProcessのWorkerにしたいかも

@tamaina
Copy link
Member Author

tamaina commented Jun 14, 2023

bullの方がなんとかなってるのはどうしてなんだろう

@yuriha-chan
Copy link
Contributor

Workerのパフォーマンスプロファイリング@13.13.2(一つだけの連合先にdeliverするテスト)
image
この条件ではあまりオーバーヘッドがあるようには見えない

@yuriha-chan
Copy link
Contributor

配送元と配送先が同一物理サーバーに乗っている場合での実験ですが

ratelimitを10とかにして、ジョブを200個くらい用意した状態でconcurrency 5のワーカーを3台位起動させるとたぶんおそらく何が起きてるかは見えるかも…?

単純にジョブがゆっくり実行されるという想定された動作になるだけで特にオーバーヘッドが増えたりしている様子はなかった

queueのratelimitの仕様も変わってこっちは結構上方修正してあげないと処理が止まっちゃうかも
(deliverJobPerSec と inboxJobPerSec などの設定、このlimitの適用範囲が完全にグローバルになってるので)

その通りで、deliverJobPerSecとinboxJobPerSecをclusterLimit倍すればよさそう

deliverJobConcurrencyはHTTPリクエストの待ち時間やDBの待ち時間に(シングルスレッドのワーカーが)ジョブを最大どれだけ並行して回すかという数なので、極端に減らさなければ特に関係なさそう。(https://docs.bullmq.io/guide/workers/concurrency)

deliverJobPerSecを上げれば500 deliver/コアくらいは捌ける模様(Workerの台数を増やして分散させても、一台あたりの効率はそれほど落ちない)

@u1-liquid
Copy link
Sponsor Contributor

Concurrencyの上げ過ぎ→ジョブごとの毎秒のCPU時間が減る→stalledタイマーの更新が間に合わなくなる→ジョブがstalled状態に→ほかのワーカーにより強制的にwaitingリストに入れられる→リスタート
の流れが起きてるのではないかとの予想ですが、小規模では再現性がよくないので何とも言えませんね…

@tamaina
Copy link
Member Author

tamaina commented Jun 15, 2023

@syuilo
Copy link
Member

syuilo commented Jun 15, 2023

アクティビティの受信や配送自体はCPU intensiveではなさそう

@tamaina
Copy link
Member Author

tamaina commented Jun 15, 2023

しかし現にCPUがめっちゃ使われている

@syuilo
Copy link
Member

syuilo commented Jun 15, 2023

動画エンコードとかそういう重い処理は同じプロセスでやると他の全てが止まるからそういう場合はプロセス分離してやってね(=sandbox processor)ってことだと思うからMisskeyおよびこのIssueとは関係なさそう

@syuilo
Copy link
Member

syuilo commented Jun 15, 2023

しかし現にCPUがめっちゃ使われている

sanbox化したところで軽くなるわけではないからなあ

@syuilo
Copy link
Member

syuilo commented Jun 15, 2023

むしろ大量にプロセス生成されてより重くなりそう

@tamaina
Copy link
Member Author

tamaina commented Jun 15, 2023

なんか無駄に抵抗してるけどとりあえず改造してみようと思ったが、Nestから剥がすのが面倒だったので断念した

(そして他のモジュールを芋蔓式に引っ張ってくる必要があるため分離したプロセスはとてもデカくなりそう)

@tamaina
Copy link
Member Author

tamaina commented Jun 15, 2023

確かに動画エンコードとかそういうワークでしか使えない

@u1-liquid
Copy link
Sponsor Contributor

https://docs.bullmq.io/guide/nestjs
これもダメそう?

@tamaina
Copy link
Member Author

tamaina commented Jun 15, 2023

https://docs.nestjs.com/techniques/queues

解説としてはこっちの方がわかりやすそう

@yuriha-chan
Copy link
Contributor

署名処理がCPU intensiveっぽいけど、すでにClusterで並行処理化できているからそれ以上の対策をする意味はなさそう(Workerの代わりにネイティブスレッドを使うようにすればメモリ使用量は削減できる可能性があるが、CPUの負荷軽減は微妙)

@tamaina tamaina changed the title bullmqがCPUリソースを消費しまくる BullMQにしてからCPU使用率が高くなる、Deliver等のキューのWaitingが増えた Jul 3, 2023
@syuilo
Copy link
Member

syuilo commented Jul 3, 2023

解決した方に報奨金を進呈

@yuriha-chan
Copy link
Contributor

BullMQがどう影響しているかはよく分からないが、プロファイラ上では署名処理が重い。
Misskeyの鍵長がRSA4096bitと、MastodonのRSA2048bitとくらべセキュリティの高い設定になっているため、この影響でCPUをバカ食いしていると思われる。
RSA2048bitで妥協するか、ECDSAやEdDSAなどの効率の良い署名アルゴリズムを使うことで、パフォーマンスを改善できる可能性がある。ECDSAやEdDSAを使うことにする場合、ユーザーの鍵を複数保存しておいて、連合先サーバーとのネゴシエーションで渡す公開鍵を決める必要がありそうである。

参考までに各アルゴリズムのOpenSSLによる速度測定例を置いておきます。
(AMD EPYC 7B12: 1CPU当たりの性能)

  • RSA 2048bit
    • 署名:1517.4/s
    • 検証:52966.6/s
  • RSA 4096bit:
    • 署名: 220.6/s
    • 検証:14481.2/s
  • ECDSA 256bit (nistp256):
    • 署名: 45247.8/s
    • 検証:14689.2/s
  • EdDSA 253bit:
    • 署名: 23028.8/s
    • 検証:8359.5/s

@yuriha-chan
Copy link
Contributor

yuriha-chan commented Jul 5, 2023

Deliverが大量に発生するとここ

const unlock = await this.appLockService.getFetchInstanceMetadataLock(instance.host);

のロックが非常に混雑して、ロックを管理しているRedisとの通信処理でNodeのCPUを大量に消費するらしい。
image

getFetchInstanceMetadataはcron的に実行する方がよさそう

@tamaina
Copy link
Member Author

tamaina commented Jul 5, 2023

getFetchInstanceMetadataLockとは関係ないけど、Redisとの通信と聞くとthis.deliverQueue.addBulkで一斉にDeliver Queueを突っ込めないかなと思った

@yuriha-chan
Copy link
Contributor

yuriha-chan commented Jul 5, 2023

ジョブキューの独自改造はわりとありだと思う
やらなければいけないというほどでもないとは思うが。

@yuriha-chan
Copy link
Contributor

鍵の変更は別Issueにしますね。

@mendakon
Copy link

mendakon commented Jul 7, 2023

再起動時と比べinboxのProcessどんどん少なくなっていく気がするのだがうちだけか

@tamaina
Copy link
Member Author

tamaina commented Jan 5, 2024

Active (concurrency)を増やすと逆にダメらしい

MisskeyIO#313 (comment)

@tamaina
Copy link
Member Author

tamaina commented Jan 5, 2024

bullmqになってからjobConcurrencyの挙動が変わったらしく、deliverJobConcurrencyは128がデフォルトだとサーバーがハングしてしまうかもしれない

deliverJobConcurrencyを8とか16あたりにするべき

最初に書いた↑の挙動はBullMQの時間計算量増加が原因かしらね

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔥high priority packages/backend Server side specific issue/PR 🐢Performance Efficiency related issue/PR
Projects
None yet
Development

No branches or pull requests

7 participants
@syuilo @tamaina @u1-liquid @SanMurakami @mendakon @yuriha-chan and others