優雅な劣化
1)アプローチの本質
Graceful degradationは、リソースが不足している、依存関係が失敗している、または負荷ピークが発生している場合に、システムをよりシンプルで便利なモードに移行するための管理機能です。目標は、二次機能と品質を犠牲にすることにより、ユーザー価値とプラットフォームの回復力のコアを維持することです。
主なプロパティ:- 予測可能性:あらかじめ定義されたシナリオと劣化「はしご」。
- ヒット半径の拘束:フィーチャーと拘束を分離します。
- 観測可能性:メトリクス、ログ、トレース「どのレベルの劣化がアクティブであり、なぜ」。
- リバーシビリティ:正常に急速に戻ります。
2)原則と境界
1.メインのものを保存します。:メインのSLA/SLO(例:「購入」「ログイン」「検索」)-優先度はセカンダリ(アバター、おすすめ、アニメーション)よりも高くなります。
2.フェイルオープンとフェイルクローズ:- セキュリティ、支払い、権利-フェイルクローズ(違反よりもより良い拒否)。
- キャッシュされたコンテンツ、ヒント、アバター-フォールバックでフェイルオープン。
- 3.時間予算:トップダウンタイムアウト(クライアント<ゲートウェイ<サービス)。期限切れ後-無期限に後退の代わりに劣化。
- 4.コストコントロール:劣化は、単なる「隠す」エラーではなく、CPU/IO/ネットワークの消費を削減する必要があります。
3)劣化レベル
3.1 クライアント/UX
スケルトン/プレースホルダとセカンダリウィジェットの「遅延」ロード。
部分UI:クリティカルブロックがロードされ、セカンダリブロックが非表示/簡略化されます。
クライアントサイドキャッシュ:last-known-good (LKG)"データが時代遅れになった可能性があります。
オフラインモード:コマンドキュー、後で繰り返します(idempotence!)。
3.2 エッジ/CDN/WAF/APIゲートウェイ
stale-while-revalidate:キャッシュを渡し、背景を更新します。
レート制限と負荷分散:オーバーロード時にバックグラウンド/匿名トラフィックをリセットします。
ジオフェンス/重み付けルーティング:トラフィックは最寄りの健康な地域に転送されます。
3.3サービスレイヤー
部分的な応答:+'warnings'データの一部を返します。
読み取り専用モード:一時的にミューテーション(フラグ)を禁止します。
Brownout:リソース集中機能の一時的な無効化(推奨、濃縮)。
適応的並行性:並行性を動的に低減します。
3.4データ/ストリーミング
TTL(一時的)による真実の源としてのキャッシュ:「何もないよりも良い」。
モデル/アルゴリズム(高速パスと正確パス)の精度を低下させました。
Defer/queue-重いタスクをバックグラウンド(outbox/job queue)に転送します。
優先キュー:クリティカルイベント-別のクラスで。
4)劣化「はしご」(プレイブック)
検索APIの例:- L0(通常)→L1:パーソナライゼーションとバナーを非表示にする→L2:同義語/ファジー検索を無効にする→L3:応答サイズとタイムアウトを300 msに制限する→L4:キャッシュからの結果を5分→L5:「読み取り専用とキャッシュ専用」+再計算のリクエストのキュー。
- トリガー:CPUの過負荷>85% p95> target、 errors> threshold、 Kafka> threshold flag、 dependency flag。
- アクション:Xフラグをオンにし、同時性をNに下げ、Yソースをキャッシュに切り替えます。
- 終了基準:10分の緑の指標、リソースのヘッドルーム。
5)意思決定方針
5.1誤った予算とSLO
brownout/sheddingトリガーとしてerror-budget burn rateを使用します。
ポリシー:「燃焼率>4 × 15分以内-L2劣化をオンにする場合」。
5.2入場管理
私たちは、p99を保証し、キューの崩壊を防ぐために、クリティカルパスの着信RPSを制限します。
5.3優先順位付け
クラス:interactive> system> background。
テナントごとの優先順位(ゴールド/シルバー/ブロンズ)と正義(フェアシェア)。
6)パターンと実装
6.1負荷取除くこと
すべてのリソースを取得する前にリクエストをドロップします。
'429'/'503'を'Retry-After'とポリシー説明(顧客向け)で返します。
Envoy(アダプティブコンカレンシー+回路破壊)
yaml typed_extension_protocol_options:
envoy. filters. http. adaptive_concurrency:
"@type": type. googleapis. com/envoy. extensions. filters. http. adaptive_concurrency. v3. AdaptiveConcurrency gradient_controller_config:
sample_aggregate_percentile: 90 circuit_breakers:
thresholds:
- max_requests: 2000 max_pending_requests: 500 max_connections: 1000
6.2ブラウンアウト(一時的な簡略化)
アイデア:リソースが不足しているときの機能の「明るさ」(コスト)を削減する。
kotlin class Brownout(val level: Int) { // 0..3 fun recommendationsEnabled() = level < 2 fun imagesQuality() = if (level >= 2) "low" else "high"
fun timeoutMs() = if (level >= 1) 150 else 300
}
6.3部分的な応答と警告
応答する'Warnings'/' degradation'フィールド:json
{
"items": [...],
"degradation": {
"level": 2,
"applied": ["cache_only", "no_personalization"],
"expiresAt": "2025-10-31T14:20:00Z"
}
}
6.4エッジ上で古くなっている間に再検証する(Nginx)
nginx proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout http_500 http_502 http_504 updating;
proxy_cache_background_update on;
6.5読み取り専用スイッチ(Kubernetes+フラグ)
yaml apiVersion: v1 kind: ConfigMap data:
MODE: "read_only"
The code should check MODE and block mutations with a friendly message.
6.6カフカ:バックプレッシャーとキュークラス
重い消費者をより小さい'maxに転換しなさい。世論調査。レコード'、生産バッチを制限します。
「critical」と「bulk」イベントをトピック/クォータで区切ります。
6.7 UI:優雅なフォールバック
「重い」ウィジェットを非表示にし、キャッシュ/スケルトンを表示し、古いデータに明確にラベルを付けます。
7)構成例
7.1イスティオアウトリエ+プライオリティプール
yaml outlierDetection:
consecutive5xx: 5 interval: 10s baseEjectionTime: 30s maxEjectionPercent: 50
7.2 Nginx:最初にナイフの下のバックグラウンドトラフィック
nginx map $http_x_priority $bucket { default low; high high; }
limit_req_zone $binary_remote_addr zone=perip:10m rate=20r/s;
limit_req_status 429;
server {
location /api/critical/ { limit_req zone=perip burst=40 nodelay; }
location /api/background/ {
limit_req zone = perip burst = 5 nodelay; # stricter
}
}
7.3フィーチャーフラグ/キルスイッチ
動的構成(ConfigMap/Consul)に保存し、リリースなしで更新します。
フィーチャーごとのフラグとグローバルフラグを分離し、ログアクティベーションを行います。
8)観察可能性
8.1メトリクス
'degradation_level {service}'は現在のレベルです。
'shed_requests_total {route、 reason}'-リセットされる金額とその理由。
'stale_responses_total'-キャッシュの発行量。
'read_only_mode_seconds_total'
'brownout_activations_total {feature}'
誤った予算:燃焼率、SLO違反の割合。
8.2トレース
スパンの属性:'degraded=true'、 'level=2'、 'reason=upstream_timeout'。
リトレイ/ヘッジクエリ間のリンクは、尾への貢献を確認します。
8.3ログ/アラート
変更原因と所有者を含む劣化レベルのスイッチイベント。
「付着」レベルのアラート(劣化が長すぎます)。
9)リスク管理とセキュリティ
認証/承認/データの整合性を低下させないでください:より良い障害。
PIIマスキングは任意のモードで保存されます。
ファイナンス/ペイメント:idempotentトランザクションのみ、厳格なタイムアウトとロールバック;疑わしい-読み取り専用/保持。
10)アンチパターン
ユーザーを促すことなく、テレメトリーなしで静かに劣化します。
負荷分散と短いタイムアウトの代わりに嵐を再試行します。
セグメンテーションなしのグローバル「スイッチ」-巨大なブラスト半径。
同じキャッシュ/キューにprodとlightweightのパスをミックスします。
永遠の劣化:brownoutとして「new normal」、忘れられた出口の基準。
Stale-write:古いデータに基づいて書き込みを試みます。
11)実装チェックリスト
- コア値と重要なユーザーシナリオが定義されています。
- トリガーと出力によるサービス/ドメーヌによる劣化ラダーをコンパイルします。
- タイムアウト/制限とサーバー側の負荷分散が入力されます。
- レート制限と優先トラフィッククラスが設定されています。
- 部分的な応答、読み取り専用、stale-while-revalidateを実装。
- 監査機能を備えた統合フィーチャーフラグ/キルスイッチ。
- 劣化レベルと原因のメトリック/トレース/アラート。
- 過負荷/失敗をシミュレートした通常のゲームの日の練習。
- SLO文書化およびエラー予算→劣化ポリシー。
12) FAQ
Q:いつbrownoutを選び、いつ取除くか?
A:失敗なしで要求のコストを削減することが目標の場合-ブラウンアウト。単純化でさえ役に立たないときにシステムを保護することが目標である場合は、ログインを削除します。
Q:ユーザーに劣化を報告することはできますか?
A:クリティカルシナリオの場合-はい(「限定モード」バッジ)。透明性はサポートと不満を軽減します。
Q:キャッシュを真実のソースにすることはできますか?
A:一時的に-はい、明示的なSLAとエージングラベル。突然変異の場合-禁止されています。
Q:レトライを「壊れた」にしないには?
A:短いタイムアウト、ジッタの指数関数的なバックオフ、idempotencyおよび試みの限界;安全な操作だけを再試行します。
13)合計
優美な劣化は、メトリクスと誤った予算の信号によってオンになっている、アーキテクチャ契約と操作の制御モードのセットです。適切に設計された階段、厳格なタイムアウトと脱出、キャッシュバックとブラウンアウト、そして強力な観測性-そしてあなたのプラットフォームは嵐の中でも有用で経済的なままです。