1 ポイント 投稿者 GN⁺ 2023-10-27 | 1件のコメント | WhatsAppで共有
  • Flawlessは、障害が発生してもコードが最後まで実行されるよう支援する耐久性のある計算実行エンジン
  • ワークフローは通常のRust関数として記述するが、ネイティブコードではなくWebAssemblyにコンパイルして決定論的な環境で実行する
  • HTTPリクエストや乱数生成のように外部世界と接する地点でのみ非決定的な副作用が発生し、Flawlessはこれをログとして保存する
  • 実行が中断されると、保存されたログを使って同じ状態まで再追従し、すでに実行済みの副作用は繰り返さない
  • 開発者はデータベースにすべての状態を直接モデリングせず、コードとローカル変数で永続状態を表現できるため、サーバー再起動後も中断地点から継続できる

コードで永続状態を表現する実行モデル

  • Flawlessは、ハードウェアやソフトウェアの障害が発生してもコードが完了するまで実行されるようにする耐久性のある計算エンジン
  • 複雑なユーザー体験には複雑なUIと状態が必要だが、すべての状態をデータベース内に直接モデリングするのは難しい
  • ユーザーが誤ってページを再読み込みしても進行状況を失わないようにするには、現代のアプリケーションには永続ストレージが必要
  • Flawlessは、永続状態をコードとローカル変数でモデリングできるようにし、アプリケーションの複雑な動作をより簡単に表現することを目指している

WebAssemblyベースの実行と障害復旧

  • ワークフローは通常のRust関数として記述され、任意のロジックを含められる
  • 関数はネイティブコードの代わりにWebAssemblyへコンパイルされ、完全に決定論的な環境で実行される
  • HTTPリクエストの実行や乱数生成のように外部世界と相互作用するときにのみ非決定性が導入される
  • Flawlessは、このような非決定的な副作用ログを保存して復旧に利用する
    • ワークフローの実行が中断された場合、再実行して同じ状態まで追いつく
    • すでに実行された副作用は再実行しない
    • 保存すべきデータ量は最小化し、それ以外は障害発生時に必要に応じて再計算する
  • この実行モデルにより、システム全体の動作をよりよく観測できる
    • 完了したワークフローや実行中のワークフローの正確な実行経路を分析できる
    • 決定論的な実行環境により、再現が難しいバグも扱いやすくなる
  • 開発者は状態保存の負担を減らし、ビジネスロジックの記述により集中できる
  • メンテナンスのためにサーバーを再起動する必要があっても、Flawlessエンジンを再起動すればワークフローは停止地点から継続して実行される
  • 2024年12月9日時点でFlawless Beta 3が提供されている

1件のコメント

 
GN⁺ 2023-10-27
Hacker News の意見
  • ワークフローのバージョン管理をどう扱うのか気になる。Temporal/Cadence のようなシステムで最も難しい問題だと思う

    • 作者です。長時間実行される、あるいは実質的に永遠に実行されるワークフローには、無停止アップグレードを許可するのが最も直感的な解決策だと思います
      新しいコードで既存の副作用ログ記録を正確に再生できる場合にだけ、アップグレードは成功します。新しいコードで追いつき、追いついたらそのまま実行を続ける方式です
      新しいコードが既存の記録と食い違うと、アップグレードは失敗し、以前のコードに戻ります。この場合は人が介入して、何が間違っていたのか確認する必要があります
      他のアプローチもありますが、実際に理解して使うにはこの方式が最も単純だと思います。開発中にも既存ログを使って、コードが分岐するかどうかをテストできます
    • すでに稼働中で進行中のワークフローがあり、ワークフローを更新しても壊れないようにする問題なのか気になる
      複数バージョンを同時に維持したいのか、それとも進行中のものを最新のワークフロー定義へ移行する方法が必要なのかも気になる
    • その通り。その部分は Conductor が代わりにうまく処理してくれる領域です
  • 私たちの分野は、いまや建築や医学にますます近づいている感じがする。こうした技術のおかげで、いじって試す段階を抜け出し、本格的な工学文化へ入っていける
    短く聞くと、こういうシステムで DoS 攻撃の影響が永続化されるのはどう防ぐのだろう

    • 「建築と医学に近づく」という表現は、機械学習が作ったような戯言に読める
      建築は規制上の制約の中で主観的な意見を扱うものに近く、医学は実験で検証される経験的知識だ。どちらも工学に似ているとは言い難い
    • 建築医学も工学分野ではないので、そちらに近づくことがなぜ工学文化への道なのかよく分からない
      建築は芸術の一形態に近く、大学の建築学科も普通は芸術系の学部にある
      医学は工学のように応用科学ではあるが、工学分野そのものではない
  • この決定性が浮動小数点計算にまで拡張されるのか気になる
    マルチプレイヤーゲームでは、クライアント状態が浮動小数点計算で少しずつドリフトを蓄積するため、サーバー状態と定期的に再同期する必要があり、歴史的にかなりつらいポイントだった

  • 副作用の状態はどこに保存されるのか気になる。例えば冪等にしたい AWS Lambda があるとすると、Lambda には実行間で維持されるローカルストレージがない
    EBS ボリュームのようなものをマウントしない限り状態は維持されないので、状態は DB に保存できると考えればいいのだろうか?

    • それは製品がリリースされたら、お金を払って使うことになる部分だと思う
  • 中核となる原理と動作を見せるアニメーションが気に入った。本当によくできている

    • ありがとう。HTML、CSS、JavaScript だけで自分でコーディングし、多くの努力と愛情を注ぎました
      コードはあまりきれいではありませんが、実装は直感的なので、確認してみたいならここにあります: https://flawless.dev/js/how-does-it-work-animation.js
    • 外部エンドポイント呼び出し時のタイムアウトのほうがずっとよく発生する失敗点なので、HTTP 実行ステップで失敗する様子も見たかった
  • 面白そうだが、関数を副作用ありとしてマークする方式が、ミスなく作りやすいのか気になる
    例で乱数生成が副作用なのは、flawless が提供する乱数生成器から来ているからだと仮定している。通常の Rust 関数でも可能だったのだろうか?
    開発者がワークフローを確認できるテストハーネスのようなものもあるのだと思う

    • flawless の作者です。WebAssembly を使えば、基本的にかなり安全にできます
      WebAssembly は、モジュール内でホスト呼び出しを明示的に宣言することを要求します。flawless が提供していない他のホスト呼び出しを使おうとすると、モジュールをインスタンス化できません
      WebAssembly エコシステムでは、いくつもの標準化作業も進んでいます。例えば Rust の rand クレートを使って WebAssembly にコンパイルすると、乱数生成のために WASI ホスト関数を使います
      wasiwasi-http などが標準化されるのを待つ間は、ひとまず独自のインターフェースを公開しています
      もちろん大きな欠点もあります。すべての Rust コードを WebAssembly にコンパイルできるわけではありません。それでも、意図しない副作用が絶対に発生しないことを保証するデフォルト拒否方式のほうがよいと思います
    • 乱数生成器と HTTP リクエストがどちらも flawless 名前空間配下にあるのを見ると、Rust エコシステム全体へアクセスさせる代わりに std::flawless のようなものを使わせることになりそうだ
      ハーネスが大半の問題を解決してくれるだろうが、どれだけ多くの機能をマッピングできるのかは気になる
      今のところは、Rust を使うスクリプティングランタイムにより近く見える
  • WASMをランタイムとして使うTemporalのRust代替のように見える。気に入った。
    windmill.devの創業者だが、私たちもRust製の耐久性エンジンを扱っている。ただし、こちらはずっと洗練されていない。ワークフローをPython/TypeScript/Go/Bashの明確なステップに分け、未完了のステップから再開するには最後のステップからやり直し、各ステップの結果をPostgres DBのjsonbに永続保存する。
    ユースケースは明らかに違うし、flawlessはサイトで述べられているように非常に軽量なので、UIフローの状態をモデル化し、小さなサーバーで数百万件までスケールさせる用途にも使えそうだ。
    素晴らしい。いつかRustがすべての分散システムを動かすようになってほしい。

  • 「他の言語で書かれた十分に複雑な並行プログラムは、その場しのぎの非公式仕様による、バグが多く遅いErlangの半端な実装を含む」— Virdingのプログラミング第一法則

    • Flawlessの目的は、何らかのワークフローの中間状態を保存し、失敗時に途中から再開することのように見える。
      これはErlangとはかなり違う。Erlangは主に、ハードウェア問題の多いプロトタイプ機器しかない状況でもソフトウェアを開発するために作られた。
      私には、この2つのアプローチは正反対に見える。Flawlessは途中でクラッシュするワークフローを完了させようとしてループにはまり得るが、Erlangはハードウェアバグを踏んだトラフィックの50%を平気で捨てられる。
    • 最初のブログ記事でErlang/OTPに言及している: https://flawless.dev/essays/when-letting-it-crash-is-not-eno...
    • これはErlangとまったく同じ問題を解いているようには見えない。
      Erlangは永続状態を実質的になくす方法で解決する。ほぼすべての状態はメッセージキューや外部DBのような場所に存在する。
      Flawlessはファイルシステムのジャーナリングに似ているが、完全に同じではない手法で問題を解いているようだ。副作用を実行するときに記録しておく方式だ。
      ファイルシステムのジャーナリングはクラッシュ後に再実行するためのものだが、ここでは再実行する必要をなくすためのものだ。
      どの領域にどれだけ合うかは明確ではないが、Erlangが適している領域との重なりは完全ではなさそうだ。
    • https://codesync.global/media/erlangrt-a-beam-vm-reimplement...
    • それなら、非公式仕様でバグの多いプログラムが期待を超えるために必要なのは、速いだけであることだ。
  • とても素晴らしい。AmbientというWASMゲームランタイムでも似た問題がある。競合するプロセスがあり、相互作用を再試行しなければならない可能性があるので、ここで示されているアプローチは興味深い。
    ところでLunaticとの関係が気になる。Lunaticも引き続き開発中なのか、これはサイドプロジェクトなのか、それとも完全に別物なのか?
    https://lunatic.solutions/

    • 良い指摘。これはLunaticのCEO兼共同創業者であるBernard Kolobaraが作ったものだ。
      https://kolobara.com
  • 「任意の計算を開始すると、システムが完了するまで実行され、すべての作業が正確に一度だけ実行されると保証される、と想像してみてほしい」
    これがどう保証されるのか気になる。分散システムで正確に一度の配信は不可能ではないのか?

    • 少なくとも一度の配信システムの上で冪等性キーを使えば、正確に一度の処理は可能だ。
    • CAP定理のことを言っているなら、少し補足説明が必要だ: https://www.infoq.com/articles/cap-twelve-years-later-how-th...
    • 不可能ではない。CAP定理でCPを選べばよい。つまり可用性を諦めるということだ。
      システムが進行できるなら、メッセージは正確に一度だけ配信される。
      存在証明が必要なら、NFSv3が1980年代にすでにこれを動かしていた。最初だったかどうかは知らない。
    • 記事には「想像してみてほしい」と書かれている。引用した文言がどこにあるのかわからないし、原文でもこの文を見つけられなかった。