TT Lab
はじめる
学ぶ 学習パス コース

ICA — Istio認定アソシエイト

応答は失敗したのに業務はコミット済み

TT Labで続きを見る

目標

実際のIstioのリトライと業務記録を比較し、応答のタイムアウトやプロセスの終了が起きても、同一の業務の重複を防ぐトランザクションの境界を実装します。

なぜ重要なのか

200は業務が1回だけ行われた証明ではなく、504はロールバックの証明ではありません。同じ注文の送信の試行ごとに新しい業務キーを作ると、重複防止の仕組みも無力になります。逆に、内容が同じ別の注文をまとめてしまうのも、エラーです。このラボは、実際のメッシュでの合成のHTTP業務と、別のトランザクションコードの修正を一緒に扱います。受講生のコードの修正は、一時的なSQLiteのテストに適用されるものであり、HTTPサーバーのコードを自動で入れ替える機能ではありません。

ステップ

  1. python3 /opt/fixtures/ica-retry/runtime.py inventoryの出力の全体を、/root/ica-retry/inventory.jsonに保存します。namespaceはica-retryで、clientとupstreamの実際のプロキシが準備できている必要があります。
  2. /root/ica-retry/routes.yamlに、networking.istio.io/v1のVirtualService retry-labを作成します。namespaceはica-retry、hostsとすべての宛先はupstream.ica-retry.svc.cluster.local、ポートは8080です。最初のルートflakyは、/flaky・/naiveのexactの2つのmatch、timeout 1s、attempts 2、perTryTimeout 1s、retryOn '503'、retryIgnorePreviousHosts falseです。2番目のlostは、/lostのexact、timeout 500ms、attempts 0です。最後のcontrolは、matchなしで同じ宛先、attempts 0です。適用後にcollect retryを実行して、retry.jsonの実際の受信・業務の回数を比較します。
  3. 同じツールのcollect timeoutを実行します。timeout.jsonには、/lostのクライアントの504、サーバーのコミット済みの応答、同じキーで/chargeを呼び出した回収結果が、一緒に入っている必要があります。数値を自分で作って書いてはいけません。
  4. collect conflictでconflict.jsonを保存します。同じ業務キーで金額を100から200に変えたリクエストが409を受け取り、既存の業務の金額は100のまま残っているかを確認します。
  5. collect durabilityでdurability.jsonを保存します。ツールは、このVMの中のupstreamのPodだけを、実際に削除・再作成します。clientのUIDは同じで、upstreamのUIDとサーバーのinstanceは異なる必要があります。同じ業務キーと応答IDは、保持されている必要があります。
  6. /opt/fixtures/ica-retry/broken.pyを/root/ica-retry/transaction.pyにコピーして、chargeのデフォルトの実行にある、コミットが分かれている欠陥を直します。initialize・charge・Conflict、after-business・after-key・after-commitの強制終了の地点は維持します。コミット前は業務・キーともに0個、コミット後は両方とも1個が残り、リトライ後に業務は常に1個である必要があります。
  7. transaction_probe.py /root/ica-retry/transaction.py identityで、同じキーの同時リクエスト8個を確認します。新しい処理は1つである必要があり、同じキーでの顧客・金額の変更はConflict、JSONの順序の変更は同じ応答、別のキーの同じ内容は別の業務である必要があります。誤った金額と未知のフィールドは、ValueErrorで拒否します。
  8. /root/ica-retry/incident.jsonに、追加の試行2・最大の試行3・naiveの業務3・重複防止の業務1を記録します。timeout_means_rollbackとexternal_payment_exactly_onceはfalseです。changed_payload_statusは実際の衝突コード、durable_scopeはsame-vm-disk、atomic_scopeはsingle-sqlite-fileと書きます。先行する実際の観測もそのまま残して、最終の採点を受けます。

参考

実際のプロキシとPodのアイデンティティの記録

inventoryコマンドで、2つのPodのUIDを記録します。Runningの名前だけを見ず、実際のプロキシが準備できているかを確認してください。

3回の受信と3回の業務を区別する

routes.yamlを適用して、collect retryを実行してください。attemptsは追加の試行であり、/naiveと/flakyの業務の帳簿を別々に見ます。

504のあとの、すでにコミットされた業務の回収

/lostの500msの予算と、リトライなしの条件を確認してください。collect timeoutは、同じ業務キーで/chargeにもう一度尋ねます。

同じキーの別の金額の拒否

collect conflictの2つのリクエストは、業務キーが同じで、金額だけが違います。既存の業務と応答が保持されているかを確認してください。

Podを入れ替えても同じ業務の応答

collect durabilityは、このVMのupstreamだけを入れ替えます。PodのUIDとサーバーのinstanceが変わり、業務IDは同じである必要があります。

コミットが分かれている欠陥をコードで直す

broken.pyをtransaction.pyにコピーして読んでください。chargeのデフォルトの実行で、業務の書き込みと重複の記録の間に、コミットが挟まっていないかを探してください。

同時リクエストと別の業務の境界

同じキーの同時リクエストは1つにまとめ、別のキーの同一の内容は、別の業務として残します。内容の変更の拒否とJSONの順序も確認してください。

応答と業務を分けた事故のレポート

最大の試行数と、実際の業務への効果を区別し、保証の範囲を、単一のSQLiteファイル・同じVMのディスクに限定してください。