Timetable

Back to Timetable
そのリトライ、死んだコネクションを使い回していませんか ── GoのHTTPクライアントとHTTP/2を実プロダクト障害から学び直す
グループ会社で内製している基盤サービスを呼び出す自社製のGo Client SDKで、ある日突然、HTTP/2コネクション起因のタイムアウトが断続的に発生するようになりました。対策前は1日最大数十件オーダーで手動対応が必要となる状態でした。根本原因をすぐに特定することはできませんでしたが、k8sのpodごとのログを観察するうちに「何らかの理由で死んだコネクションを net/http が再利用し続けている」という仮説にたどり着きました。実際、リトライを追加するだけでは、同じ死んだコネクションでもう一度失敗するだけで、問題は解決しませんでした。
本セッションでは、この障害の調査から解決までを追体験する形で、GoでHTTPクライアントを実装・運用する際の判断ポイントを共有します。
扱う内容:
- HTTPコネクションの基本と、HTTP/2のコネクション管理の特徴(本障害の理解に必要な範囲で)
- net/http のコネクションプールの仕組みと、MaxIdleConnsPerHost や IdleConnTimeout などの各パラメータが何を制御しているのか
- GoでHTTPクライアントを実装するうえでの勘所と落とし穴:
- 単純にリトライしても、死んだコネクションを再利用してまた失敗するという罠
- ReadIdleTimeout + PingTimeout < リクエストのcontextタイムアウト のように、各パラメータを根拠を持って決める方法
- リトライをどのレイヤーに入れるか、APIの冪等性も踏まえた設計判断
- その他、net/http に関して実際に踏んだ罠
仮説に基づく対策を入れた経路では問題が収束し、入れていない経路では再発し続けたことで、見立ての正しさを確認できました。コネクション断自体は今も起きていますが、この設計に変えてからは手動対応が一切不要となり、障害件数ゼロを維持しています。コネクション断は起きる前提で、障害にしないための設計と設定値の決め方を、同じ問題に直面しうるチームがそのまま使える形で持ち帰ってもらいます。
前提知識: net/http でAPIを呼び出した経験があれば十分です。HTTP/2の事前知識は不要で、セッション内で必要な範囲を説明します。
Yusa Matsuda REALITY株式会社
シンプルな言語と豪奢なご飯が好きです。