HN 日本語サマリー

← 一覧へ戻る
インフラ・DevOps

マシンは起動するが、応答が消えるとき

When the machine boots but the reply disappears (mainbrella.com)

4 pointsby cs19961 コメント

要約

この記事は、クラウドインフラストラクチャにおける、リクエストがサーバーに到達したかのように見えても応答が返ってこないという問題について解説しています。これは、リソースの競合やネットワークの問題、あるいは非同期処理の複雑さに起因する可能性があります。Mainbrellaでは、Cloudflare Durable Objectsを活用して、リソースの予約、起動、および状態管理を原子的に行うことで、このような問題に対処しています。

全文翻訳

← エンジニアリングブログ マシンは起動するが、応答が消えるとき 2026年10月7日 · Mainbrella Engineering サーバーにLinuxマシンを作成するように依頼します。マシンは起動します。応答が消えます。クライアントの立場から見ると、これはサーバーに届かなかったリクエストのように見えます。再試行するのは合理的です。2台目のマシンを起動すると、復旧コストが失敗コストよりも高くなります。これはMainbrellaのバックエンドへの有用な入り口となります。1台のマシンを十分に追跡すると、同じ問題が繰り返し発生します。呼び出し元が結果を見ることなくコマンドを実行できたり、ネットワークメンバーシップよりも長くプライベートなリクエストが存続したり、復元に必要なハンドルを残さずにディスクキャプチャが成功したりします。各境界では、再試行が何を行うことを許可されるかについての決定が必要です。分析を実行し、別のコンテナからデータを読み込み、メトリクスを書き出すという、説明的なジョブを追ってみましょう。そのマシンはスロットc17を占有します。ファイル名とスロットは例であり、以下のメカニズムはオープンソースのバックエンドから来ています。Linuxが起動する前、つまり所有権と予算を決定する必要がある場所から始めます。 1つの場所が最後のスロットを誰に割り当てるかを決定する アカウントがスロットを1つだけ持っている間に、2つの作成リクエストが到着する可能性があります。カウンターを読み取り、マシンを起動し、その後カウンターを更新することは、両方のリクエストに勝つ機会を与えます。それに気づく頃には、高価な部分はすでに終わっています。各アカウントにCloudflare Durable Objectを提供します。これは、独自のストレージを持つ永続的なコーディネーターです。公開APIは、認証されたユーザーと支払い済みエンタイトルメントを解決し、その後、アカウント:<userId>としてそのコーディネーターに対処します。各マシン・スロットは個別のDurable Objectを持っています。c17の場合、その名前はuser:<userId>:slot:17です。最初(スロット1)は古い名前user:<userId>と公開IDsmallを保持します。そのIDはマシンのサイズを選択しません。アカウントコーディネーターは入場をシリアライズします。リクエストは、ランタイムに起動を依頼する前に、スロット、月間開始、およびコンピューティング割り当てを予約する必要があります。したがって、最初のリクエストは、最初のマシンがまだ起動中であっても、占有された容量を確認します。アカウントコントローラーは、プロミス・テールを使用してキューを明示的に実装します。入場決定内のawaitは、次の決定がそれをすり抜けることを許しません。すべてが準備完了になるまでこのロックを保持すると、それらの起動時間もすべてシリアライズされます。我々は、耐久性のある予約とそれ以外のプロビジョニングの後にそれを解放します。1つのアカウントが順序通りに決定を下します。それらのランタイムは一緒に起動できます。短い共有決定は、長い独立した作業の前に来ます。時間は模式的です。重なり合うバーは並行性を示しており、測定された起動遅延ではありません。これの区別には特に有用なテストがあります。Builderアカウント(5つのスロットを持つ)で6つの同時リクエストを送信し、すべてのランタイムの準備完了チェックをゲートの後ろに保持します。5台のマシンがゲートが開く前に起動に到達します。6番目のリクエストは競合を受け取り、アカウントは5回の起動を記録します。これは、設計の両方の半分、つまり排他的入場と並列プロビジョニングをチェックします。所有権は、この調整が開始される前に確立されます。認証アダプターは、APIキーまたはログインセッションを受け入れます。明示的に無効なBearer認証情報は、有効なブラウザCookieが付属していても、認証に失敗します。内部リクエストビルダーは、アカウントIDとエンタイトルメント自体を供給します。呼び出し元にx-mainbrella-userヘッダーを選択させると、構築したアカウント境界が損なわれます。 レシートはマシンが存在する前に作成されます 分析.pyジョブの場合、クライアントはPOST /containersでIdempotency-Keyを提供します。そのキーは「マシンを作成するこの特定の試み」を意味します。アカウントは、そのキーに属するスロットと予約、および要求された構成のフィンガープリントを記録します。キーを再利用しながら画像、サイズ、またはその他のフィンガープリント選択を変更すると、競合が発生します。重要な書き込みは小さいです。以下はcontainer-account-core.jsの関連部分で、周囲の検証は省略されています。 const reservationId = ++state.nextReservationId; state.reservations[slot] = reservationId; const creation = { id: crypto.randomUUID(), slot, reservationId, fingerprint, expiresAt: this.now() + CREATION_RETENTION_MS, }; await this.ctx.storage.put({ [KEY]: state, [CREATION_PREFIX + idempotencyKey]: creation, }); このマルチキー書き込みは、請求された予約と作成レシートをアトミックにコミットします。予約されていないスロットのレシートや、キー付きの再試行で見つけられない請求済みスロットは望ましくありません。その後初めて、コントローラーは起動をディスパッチします。 次に、応答を失います。一致する再試行は、新しい入場を試みる前にレシートを見つけます。予約が保留中の間、90秒の調整ウィンドウがあります。その後、コーディネーターはランタイムに実際に何が存在するかを尋ねます。実行中のマシンが見つかった場合、別の起動を請求することなく、そのマシンを返します。再試行は、あいまいな予約を2度とディスパッチしません。レシートは24時間持続します。マシンが停止しているか、スロットが再利用されている場合、同じ保持されたキーはcreation_no_longer_runningを返します。静かに交換機を起動することはありません。交換機を希望するクライアントは、新しいキーで新しい作成試行を行います。これも、クライアントが問い合わせに必要なIDを忘れた場合、サーバーサイドの重複排除はほとんど役に立たないため、クライアントがキーとリクエストを送信する前に保存すべき理由です。 何が準備完了を確立するか? ランタイムコントローラーは、選択されたイメージをsleep infinityをエントリーポイントとして起動し、その後uname -aを実行します。コマンドは60秒以内に正常に終了する必要があります。これにより、ゲストがコマンドを実行できることが確立されます。私たちのPython分析には、まだ独自の依存関係とチェックが必要です。応答するカーネルは、財務計算を証明できません。 昨日のメッセージが明日のマシンに到着する可能性 最初の起動のディスパッチが遅延したと仮定します。その間、アカウントは予約をキャンセルし、c17を解放し、そのスロットを交換機に割り当てます。古いディスパッチが最終的に到着します。そのターゲットは依然として同じランタイムオブジェクトです。スロットを名前で検索しても、このメッセージが起動する権利があるかどうかはわかりません。各入場した起動には、増加する予約番号が割り当てられます。ランタイムでは、2つのハイウォーターマークを永続化します。最も新しい受け入れられた起動と、最も新しいキャンセルです。キャンセルは、破壊する実行中のゲストが存在しない場合でも、そのフェンスを書き込みます。そのため、後から到着したものがキャンセルされた作業を復活させることはできません。破線の対角線をたどってください。最初の起動は交換機後に到着します。キャンセルフェンスと受け入れられた予約により、その古さがランタイムに可視化されます。逆レースも重要です。予約41の遅延したクリーンアップが、予約42のマシンを停止させてはなりません。ランタイムのDELETEパスはキャンセルマークを進めますが、キャンセルが受け入れられた起動よりも古い場合、ゲストはそのままにします。 アカウントに戻ると、起動の完了は、保留中の状態をクリアするために、現在のスロット予約と一致する必要があります。古い成功した応答も、交換機に対して権威を持ちません。予約番号は内部ライフサイクルメッセージを保護します。公開コマンドとファイルリクエストは、{ id, createdAt }で実行中の世代を識別します。スロットIDは再利用可能ですが、世代は再利用できません。タイムスタンプ形状の表現にもかかわらず、createdAtはmax(now, previousCreatedAt + 1)として計算されます。同じミリ秒でマシンを再作成したり、ウォールクロックを巻き戻したりしても、新しいゲストには異なるIDが与えられます。返された実行中のコンテナから両方の値を取得してください。c17のみのクリーンアップリクエストは、どのライフタイムを意味するかを表現できません。ライフサイクルテストは、クロックを進めることなく、古い起動ディスパッチを解放する前に、意図的にスロットを停止して再利用します。これは、別の成功したhello-world起動よりも、より明らかになるチェックです。 ハードデッドラインは入場の一部です 私たちのマシンは、コンピューティングを使い続ける許可も必要です。月間のカウンターチェック