Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
HTTP Retry の実装
Search
Shota Iwami
November 06, 2023
Programming
2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
HTTP Retry の実装
社内勉強会でのLTです
Shota Iwami
November 06, 2023
More Decks by Shota Iwami
See All by Shota Iwami
モノレポにおけるエラー管理 ~Runbook自動生成とチームメンションの最適化
biwashi
2
1.1k
OpenTelemetry の Log を使いこなそう
biwashi
7
2.4k
Monorepo Error Management: Automated Runbooks and Team-Targeted Alert Distribution
biwashi
2
1.2k
スタートアップ創業期を支えるオブザーバビリティ基盤のこれまでとこれから
biwashi
10
1.8k
モノレポ開発のエラー、誰が見る?Datadog で実現する適切なトリアージとエスカレーション
biwashi
7
1.9k
k6を活用した再現性・拡張性の高い負荷試験基盤の構築
biwashi
13
4.4k
Datadogマニアック機能活用術
biwashi
7
4.9k
feature flag と OpenTelemetry
biwashi
7
2.5k
OpenFeatureと自動生成を活用したフィーチャーフラグの宣言的集約管理
biwashi
20
7.7k
Other Decks in Programming
See All in Programming
すこし踏み込む CancellationToken
htkym
2
1.7k
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
150
[Dev Group Paris Octobre 26] Agentforce, SIforce, Claudeforce, Slackbot… on s'y retrouve ?
nabondance
0
110
Performance Optimization With LLMs
xleitix
0
130
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
750
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5.2k
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
TechTown - Creating Composable Callables in Contemporary C++
rollbear
0
130
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
The Rails Doctrine Decade
koic
2
590
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.2k
Featured
See All Featured
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
570
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
The World Runs on Bad Software
bkeepers
PRO
72
12k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
Optimizing for Happiness
mojombo
378
71k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
730
Deep Space Network (abreviated)
tonyrice
0
370
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
570
The SEO identity crisis: Don't let AI make you average
varn
0
590
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Discover your Explorer Soul
emna__ayadi
2
1.3k
Transcript
HTTP Retryの実装 AI事業本部 アプリ運用センター 岩見彰太
自己紹介 岩見 彰太 趣味:サックス・ドローン・カメラ AI事業本部 小売DX アプリ運用センター 22卒バックエンドエンジニア B_Sardine
事の発端 とあるAPIに対して特定のステータスコードの時に Exponential Backoffによるリトライを実装したい
最初こんな感じで実装してみた ということで…
client.Do(req)を実行する responseのステータスコードが429なら エラーを返す エラーだった時にリトライする cenkalti/backoff 用メソッド maxRetryNumberで設定 した回数だけリトライする
最初の1回目以降、Request Bodyが空だと怒られて Do がエラーになる 適当なサーバを立てて叩いて見ると…
こんな感じで、Bodyを入れ直すと通る Bodyの巻き戻し. 入れ直しが必要 先に結論
Requestの構造体を見てみる Bodyはio.ReadCloserというインターフェース型 今回入れた具象型はbytes.Buffer 複数回リトライする場合, これが複数回実行される bytes.Bufferの構造体を見てみる lastReadという読み切った場所を内部で保存してる なぜなくなる? リトライする場合は Request.Bodyを初期状態に戻す必要がある
つまり…
http.Clientの中のTrasport.roundTripがリトライ処理し てる ネットワークエラーとかになった時にリトライしてる rewindBodyというメソッドを呼んでる Request.Bodyを閉じる body, err := req.GetBody()でRequst.Bodyのコピーを取 り出す
取り出したものをもう一度reqに入れる rewindBodyの流れ 1. 2. 3. 実はnet/httpもリトライしてる コネクションの確立とかコネクションプールの管理を行なってる Transport
*bytes.Buffer <----- 今回の場合 *bytes.Reader *strings.Reader Request.Bodyの具象型が以下の時に GetBodyがセットされる io.NopCloser は何もしない io.ReadCloser
(Bodyで指定されているinterface型)を実装できる req.GetBody()は Request作成時に作られる
Transport.roundTripでも終了判定している リトライをする場合、呼び出し元のcontextを伝播す る必要がある 同じように判定する必要がある Contextの終了を確認する
レスポンス内容はio.ReadCloserの Response.Bodyから読み取れる 呼び出し側で最後まで読み取ってから Close しな いと keep-aliveの TCPコネクションが再利用さ れない レスポンスを返した後に接続を維持し、次のリク
エストを送るときにその接続を再利用して送ること ができる Keep-AliveはResponseが読み切られてCloseした タイミングで再利用できるようになる > Bodyを閉じるのは呼び出し側の責任である。 > デフォルトの HTTP クライアントの Transport は、Body を最後まで読んで閉じな いと、 HTTP/1.x の "keep-alive" TCP コネクションを再利用しないかもしれません。 Keep-Alive http.Response.Bodyを 読み切ってから閉じる
Transport 内部では、connectMethodKey(接続先) 単位で idel 状態のTCPコネクションや 確立待ちのキューが管理されている これがデフォルトの場合はDefaultTransportが使用される 90s: IdleConnTimeout(リクエストが終わってもコネクションが維持される時間) 2:
MaxIdleConnsPerHost(接続先ごとのKeep-Aliveの最大数) TransportでのTCPコネクションの管理
CloseIdleConnections()でコネクションプールを 一括で閉じることができる リトライ終了後に意図的に解放したい場合は使える (これを呼ばない場合、IdleConnTimeoutが過ぎると 自動的に解放される) コネクションプールを閉じる
リトライが必要となる場面(429 Too Many Requests)では、短期間で同じ宛先にリクエスト する場合 そうなると、 MaxIdleConnsPerHost だと少ない可能性が高い リトライしている期間中占有してしまい、解放まで時間がかかる可能性があるから 場合によっては専用の
Transport を作成した方がいい この場合、使わないのに IdleConnTimeout で設定されている時間分 Keep-Alive が保持 されて、コネクションリソースを消費してしまうので、リトライが終了した後は CloseIdleConnections を読んでコネクションプールを開放するべき (終了したらコネクションプールを閉じる) リトライ用のTransportを別で用意するべき?
ただリトライしたいだけなのに 考えること多くてめんどくさい… ここら辺まるっとやってくれる便利なライブラリないのか……
今まで説明してきたようなことが考慮されてる TransportはMaxIdleConnsPerHostを増やし て、リトライ後には閉じるようになっている net/httpと同じように使えて直感的 -> 結局これを使いました Hashicorp製 hashicorp/go-retryablehttp ありました
まとめ リクエストの内容(Request.Body)をリトライ前に巻き戻す Request.Context()の終了を確認する リトライ前にResponse.Bodyを全て読み切ってから閉じる デフォルトのTransportを使用してコネクションプール管理するか検討する hashicorp/go-retryablehttpの使用を検討する ちなみに、AWS SDK for GoとかでAPIコールする場合は、勝手にリトライしてくれるようになってる