$30 off During Our Annual Pro Sale. View Details »

ジョブキューシステムFireworqのアーキテクチャ設計と運用時のベストプラクティス

 ジョブキューシステムFireworqのアーキテクチャ設計と運用時のベストプラクティス

INA Lintaro

March 19, 2023
Tweet

More Decks by INA Lintaro

Other Decks in Technology

Transcript

  1. ジョブキューシステム
    Fireworqのアーキテクチャ設計と
    運用時のベストプラクティス
    INA Lintaro
    id:tarao @oarat
    2023-03-19 YAPC::Kyoto 2023

    View Slide

  2. 自己紹介
    2
    id:tarao
    @oarat
    @tarao
    エンジニア (バックエンド)・エンジニアリングマネージャ
    ● 2013~ はてなに新卒入社
    ● 2015~ はてなブックマークのシステム刷新 (テックリード)
    ● 2021~ エンジニアリングマネージャ
    今回に関連する話
    ● 10年でどう変わった? はてなブックマークでのPerlの
    使い方
    YAPC::Nagoya::Tiny 2019, 名古屋市中村区,
    November 2019 (ゲストスピーカー)

    View Slide

  3. 3
    Fireworq is 何?

    View Slide

  4. Fireworq is 何?
    ● ジョブキュー (メッセージキュー)
    ● Go製
    ● ストレージはMySQL
    ● at-least-once
    4

    View Slide

  5. Fireworq is 何?
    ● HTTPでジョブを投げる
    ● 指定ワーカーにPOSTしてくれる
    ● 投入元 = ワーカー なら
    つまり非同期処理
    5

    View Slide

  6. Fireworq is 何?
    ● HTTPでジョブを投げる
    ● 指定ワーカーにPOSTしてくれる
    ● 投入元 ≠ ワーカー なら
    つまりメッセージング
    6

    View Slide

  7. 7
    以前の
    ジョブキュー
    ソリューション

    View Slide

  8. TheSchwartz + WorkerManager
    困りどころ
    ● Perlでしか使えない
    ● 重いジョブによるリソース占有
    ● ワーカー並列数を増やすと詰まる
    ● ワーカーをメンテしづらい
    ○ エントリーポイントが特殊
    ○ 環境セットアップが特殊
    8

    View Slide

  9. TheSchwartz + WorkerManager
    困りどころ
    ● Perlでしか使えない
    ● 重いジョブによるリソース占有
    ● ワーカー並列数を増やすと詰まる
    ● ワーカーをメンテしづらい
    ○ エントリーポイントが特殊
    ○ 環境セットアップが特殊
    9

    View Slide

  10. TheSchwartz + WorkerManager
    ● 複数のワーカーが一斉にジョブを掴む
    ● ワーカーを増やしていくと詰まる
    10

    View Slide

  11. 11
    Fireworqの設計

    View Slide

  12. 設計思想
    12
    Portability 言語非依存 (インタフェースはHTTP)
    Reliability RDBMS (MySQL)で永続化
    Availability プライマリ/バックアップのノード構成
    Scalability 単一ディスパッチャ+多数のワーカー
    Flexibility 複数のキューを動的に設定可能
    APIや管理Webコンソールで操作可能

    View Slide

  13. アーキテクチャ
    ● 単一ディスパッチャでポーリング
    13

    View Slide

  14. しくみ - MySQLエンジン
    ● 1テーブル = 1キュー
    ● INSERTとUPDATEを
    競合させない
    ● TheSchwartzや
    MogileFSもだいたい同じ
    14
    id next_try status
    6 12:05 claimed
    5 11:05 claimed
    4 10:32 claimed
    3 10:27 claimed
    2 09:41 grabbed
    1 09:07 grabbed
    現在時刻
    新規ジョブ
    INSERT位置
    次に掴む
    UPDATE
    claimed

    grabbed

    View Slide

  15. しくみ - ノード昇格
    ● プライマリ
    ○ GET_LOCK成功
    ● バックアップ
    ○ GET_LOCK待ち
    ○ INSERTは可
    ○ プライマリが落ちると
    直ちに昇格
    15

    View Slide

  16. 16
    TheSchwartzからの移行

    View Slide

  17. 元のワーカーの想定
    package My::Worker
    use parent qw(TheSchwartz::Worker);
    sub work {
    my ($class, $job) = @_;
    ...
    $job->completed;
    }
    17

    View Slide

  18. TheSchwartz::Fireworq
    ワーカーをweb app化: app.psgiに以下を追加
    enable ‘TheSchwartz::Fireworq’, path => ‘/work’;
    18

    View Slide

  19. TheSchwartz::Fireworq
    ジョブの投入側: クライアントが変わるだけ
    my $client = TheSchwartz::Fireworq->new(
    server => 'http://localhost:8080', # Fireworq
    worker => 'http://localhost:5000/work', # ワーカー
    );
    $client->insert('My::Worker', { @_ });
    19

    View Slide

  20. 20
    Fireworqの
    運用プラクティス

    View Slide

  21. 複数キューの使い分け
    ● 時間のかかるジョブはキューを別にする
    ● ジョブカテゴリは細かく分けておく
    ○ カテゴリごとに配送先キューを設定するため
    21

    View Slide

  22. スロットリング
    ● 前提: ジョブは羃等にしておく
    ● TheSchwartzではuniqkeyで可能だった
    ○ 本当の意味のスロットリングではない
    ● 自前でやる必要がある
    ○ キーごとに最終実行予定時刻を記録すれば可能
    ○ 投入ジョブの実行予定より後の予定があればスキップ
    ○ なければrun_afterでインターバルを空けて投入
    22

    View Slide

  23. 失敗時の再送
    ● 自動で再送される
    ○ 指定したmax_retriesの回数以内の場合
    ○ ジョブを掴んでいる途中でFireworqが落ちた場合
    ● それでも失敗したもの(permanent failure)
    ○ GET /queue//failedで一覧が取れる
    ○ POST /job/で必要に応じて再投入する
    23

    View Slide

  24. Mackerelで監視
    ● mackerel-plugin-fireworq
    ○ キューやノードの状態のメトリックを取る
    ● mackerel-check-fireworq
    ○ ジョブの失敗(permanent failure)をアラート
    24

    View Slide

  25. 25
    まとめ

    View Slide

  26. まとめ
    ● Fireworqはジョブキュー
    ○ 言語非依存でスケールする
    ○ ワーカーもweb appのためわかりやすい
    ● TheSchwartzからの移行は簡単
    ● 本番運用に必要なものは揃っている
    ● コントリビュータ・メンテナ募集中
    26

    View Slide

  27. 27
    質問?

    View Slide

  28. 28
    FAQ

    View Slide

  29. Q. HTTP以外はサポートしないの?
    A.
    ● gRPCとか? HTTP/2?
    ○ サポートしてもよいかも
    ○ コントリビュータ歓迎
    ● 必要なほどパフォーマンスがシビアな状況?
    ○ 今のところ聞いたことがない
    ○ 試してみてHTTPでは無理だったらおしえてください
    29

    View Slide

  30. Q. MySQL以外のストレージではダメ?
    A.
    ● 内部コード的には変えられる
    ○ インタフェースさえ満たせばなんでもよい設計
    ● 当初はRedisエンジンも実装予定だった
    ○ 単にめんどうでやってないだけ
    ○ コントリビュータ歓迎
    30

    View Slide

  31. 31
    おわり

    View Slide