代表的な面接トピック

システムデザイン面接:Wasm Component Model プラグインランタイムをどのように設計しますか?

システム設計難しい
Offer.cc 編集チーム公開日 更新日

質問

ある SaaS プラットフォームでは、サードパーティが Rust、Go、Python でプラグインを作成し、テナントのリクエスト内で変換やバリデーションを実行できるようにしています。WIT インターフェース、機能、互換性、リソース制限、署名、オブザーバビリティ、ロールバックを網羅した Wasm Component Model プラグインランタイムを設計してください。

プロンプトとコンテキスト

このプラットフォームでは、サードパーティ製プラグインがファイル変換、フィールドバリデーション、テナント固有のルールを処理できるようにします。プラグインはさまざまな言語で記述されており、直接信頼することはできません。1 つの暴走したプラグインがホストプロセスを停止させてはなりません。インターフェース定義、ロード、分離、リソースバジェット、互換性のあるアップグレード、リカバリを網羅した Wasm Component Model ランタイムを設計してください。

Component Model は、コンポーネント、インターフェース、world を使用してインポートとエクスポートを記述します。WIT はインターフェース記述言語であり、Canonical ABI は高レベルの値が言語の境界をどのように越えるかを定義します。面接では、これらの標準を実行可能なマルチテナントプラグインプラットフォームに変換できるかどうかが評価されます。

面接官が評価するポイント

インターフェースと型のガバナンス、最小権限の原則、インスタンスの分離、CPU とメモリのバジェット、タイムアウトとキャンセル、コンポーネントの署名とプロベナンス(出所)、バージョン互換性、再現性、ログとメトリクス、カナリアリリース、ロールバックを網羅してください。

確認すべき明確化のための質問

  • プラグインは同期リクエスト内で実行されますか、それとも非同期ジョブ内で実行されますか?また、レイテンシとスループットのバジェットはどのくらいですか?
  • どのファイル、ネットワーク、キー、クロックの機能が必要で、テナントはどのように分離されますか?
  • インターフェースはリソース、ストリーム、future を使用できますか?それとも境界付きの値型のみですか?
  • アップグレード後も古いテナントの再現性を維持する必要がありますか?互換性期間はどのくらいですか?
  • 違反やタイムアウトが発生した場合、即座に終了すべきですか、隔離してリトライすべきですか、それともホストのフォールバックを使用すべきですか?

30秒での回答

「限定的でバージョン管理された WIT world を定義し、必要なビジネス機能のみを公開します。コントロールプレーンはプロベナンス、署名、依存関係を検証し、データプレーンは CPU、メモリ、出力、デッドラインの制限を設けた隔離された Wasm インスタンスを実行します。インターフェースの互換性を確認し、カナリアアップグレードを実施しながら、バージョン、テナント、バジェット消費量、結果のサマリーを記録します。タイムアウトや違反が発生した場合はそのプラグインのみを停止し、安全なホストのデフォルト値を返します。」

ステップごとの詳細解説

ステップ 1: WIT インターフェースとデータ境界の定義

明示的なエラー enum、最大長、エンコーディングを持つ、境界付きの record、variant、list、result を優先します。ホストオブジェクトや隠れたグローバル状態を公開してはなりません。各 world には、そのプラグインクラスに必要なインポートとエクスポートのみを含める必要があります。

text
world transform-v2 {
  export transform: func(input: record { bytes: list<u8>, mime: string }) -> result<list<u8>, transform-error>
}

インターフェースレジストリには、パッケージ名、バージョン、互換性ルール、バインディングツールチェーンのバージョンを記録します。制限のない入力をリストとして見せかけるのではなく、大規模データ用の独立したバックプレッシャー対応ストリームインターフェースを定義します。

ステップ 2: 機能とテナントの分離の構築

呼び出しごとに新しいインスタンスを作成します。デフォルトでは、ネットワーク、ファイルシステム、環境、乱数生成、キーの機能は提供しません。アクセスが必要な場合は、テナント、プラグイン、リクエストのアイデンティティにバインドされた明示的なホスト関数を付与します。

機能トークンは有効期限が短く、監査可能で、テナント間で再利用(リプレイ)できないようにする必要があります。ホスト API は最小限に保ち、プラグインにホストプロセスのポインタやフィルタリングされていないシステムハンドルを渡してはなりません。

ステップ 3: バジェットと終了処理の設定

インストラクション数または時間のバジェット、リニアメモリ制限、テーブルおよびスタック制限、出力上限、同時実行クォータを設定します。デッドラインを設定してキャンセルを伝播させ、バジェットを超過したインスタンスを終了してその理由を記録します。リトライが安全かどうかは、冪等性を確認した後にのみ判断します。

ユーザーリクエスト内で無制限に待機するのではなく、長時間のジョブには非同期キューとリースを使用します。1 つのテナントが共有実行プールを使い果たさないように、テナントとプラグインの両方で計測(メーター)とレート制限を行います。

ステップ 4: コンポーネントと ABI の互換性の処理

リリース前に、WIT world と依存関係をパースし、互換性ルールに照らしてインポートとエクスポートをチェックします。Canonical ABI は値の表現を標準化しますが、ビジネス上の互換性を保証するものではありません。enum の追加、エラーの意味の変更、単位の変更には、引き続きコントラクトテストが必要です。

古い world 用のエグゼキュータとバインディングを維持し、プラグインがサポートするインターフェースバージョンを宣言できるようにします。デフォルトバージョンを切り替える前に、デュアルリードまたはシャドウ実行を使用して結果とリソースの変化を比較します。

ステップ 5: サプライチェーンとロードの検証

不変のアーティファクトダイジェストを生成し、コンポーネント、WIT world、依存関係のロックファイル、ビルドメタデータに署名します。コントロールプレーンは、信頼できる署名者とスキャン済みの依存関係のみを許可します。ロード時には、ダイジェスト、署名、ターゲットランタイムバージョン、失効状態を再確認します。

登録、承認、失効、ロールバックを監査ログに記録します。ランタイムで未登録のコンポーネントをダウンロードしてはなりません。変更されたタグによって実行中のコードが暗黙的に変更されないよう、キャッシュはダイジェストでアドレス指定します。

ステップ 6: オブザーバビリティ、カナリア、リカバリ

すべての呼び出しについて、プラグインダイジェスト、インターフェースバージョン、テナント、レイテンシ、リソース使用量、結果ステータス、エラークラスを記録します。ログにユーザーペイロードやキーを含めてはなりません。タイムアウト、メモリ枯渇、拒否率など、プラグインおよびテナントごとにメトリクスを集計します。

新しいバージョンを合成トラフィックまたは少数のテナントセットでカナリアリリースし、結果の差分とテールレイテンシを比較します。リグレッションが発生した場合は、そのバージョンを停止して失効させ、以前のダイジェストに戻します。プラグインの障害がコアビジネスロジックに波及しないよう、ホストは安全なデフォルト値を提供します。

優れた回答例

私なら、境界付きの型を持つ限定的でバージョン管理された WIT world を定義し、必要なホスト機能のみを付与します。各リクエストには、CPU、メモリ、出力、デッドライン、同時実行数の制限を持つ隔離されたインスタンスが割り当てられます。コントロールプレーンは署名、ダイジェスト、依存関係、失効をチェックします。アップグレードはコントラクトチェック、シャドウ実行、小規模なカナリアリリースを通過させます。オブザーバビリティはプラグイン、テナント、バージョンごとに分割され、タイムアウトや違反が発生した場合はそのインスタンスのみを強制終了し、安全なホストのデフォルト値を返します。

よくある間違い

  • ホストオブジェクトを直接公開する → 権限昇格やテナント間の漏洩につながる → 最小限のホスト関数を使用する。
  • メモリのみを制限し時間を制限しない → 無限ループがプールを消費し続ける → CPU、デッドライン、同時実行のバジェットを設定する。
  • Canonical ABI をビジネス互換性とみなす → 単位やエラーセマンティクスが呼び出し元を破壊する可能性がある → コントラクトテストと world のバージョンを維持する。
  • 変更可能なタグでキャッシュする → タグの移動によって未知のコードが実行される → 不変のダイジェストと署名でアドレス指定する。
  • すべての障害をリトライする → 冪等性のない副作用が繰り返される → 冪等性を宣言し、エラーを分類する。

フォローアップの質問と回答

フォローアップ 1: なぜプロセスやコンテナを使用しないのですか?

脅威モデルとバジェットによります。Wasm インスタンスは起動が速く、制御されたインターフェースを公開しますが、ランタイムのパッチ適用、ホストの堅牢化(ハードニング)、多層防御を置き換えるものではありません。リスクの高いプラグインは、より強力な分離レイヤーで実行することも可能です。

フォローアップ 2: 大容量ファイルのストリーミングをどのようにサポートしますか?

同時実行数、チャンクサイズ、累積出力に制限を設けた、バックプレッシャー対応のストリームインターフェースを定義します。テールが長い処理には非同期ジョブを使用し、キャンセルとリースの状態を監査します。

フォローアップ 3: 2つのバージョンが同等であるかどうかをどのように判断しますか?

固定された入力コーパスをシャドウ実行で実行し、正規化された結果、エラークラス、レイテンシ、リソース使用量を比較します。宣言された浮動小数点や順序の違いを許容し、許容できない差異がある場合はリリースをブロックします。

フォローアップ 4: プラグインがネットワークアクセスを必要とする場合はどうしますか?

テナントおよびドメインが許可リストに登録されたプロキシ機能を付与し、タイムアウト、レスポンスサイズ制限、監査記録を設定します。デフォルトで任意の通信先アドレスを拒否し、失効時には機能トークンを即座に無効化します。

公開情報ソース

関連する質問

関連面接ツール

システム設計の回答には「回答する」を使用

まず要件を明確にし、スケール、アーキテクチャ、コンポーネント選定、トレードオフの順に進めます。

ツールを見る