Home
Explore
Submit Search
Upload
Login
Signup
Advertisement
Check these out next
alieaters_tokyo_20200325_yoshimura
Masaki Yoshimura
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
Iwana Chan
Varnishのログの眺め方
Iwana Chan
Stroustrup10章雑感
31 00
Openjdk 入門してみた話
Tokuhiro Matsuno
マスタリングJUNOS DHCP
ZenSekibe
RelaxCafe@CouchDB break.4
Yohei Sasaki
Varnish 4.0 Release Party in Tokyo発表資料
Iwana Chan
1
of
35
Top clipped slide
リトライでtime.Sleepを使ったら積んだ話
Aug. 6, 2020
•
0 likes
0 likes
×
Be the first to like this
Show More
•
2,063 views
views
×
Total views
0
On Slideshare
0
From embeds
0
Number of embeds
0
Download Now
Download to read offline
Report
Engineering
trouble shooting when you using time.Sleep() in retry.
ssuser329cba
Follow
Advertisement
Advertisement
Advertisement
Recommended
Using context.context in context
James Kirk
130 views
•
24 slides
ジャパネットQB GPars
Takahiro Sugiura
1.8K views
•
47 slides
CouchDB JP & BigCouch
Yohei Sasaki
1.8K views
•
40 slides
NanoStrand
Masashi Umezawa
813 views
•
26 slides
Tarantubeでメッセージキューを使い倒す
Masashi Umezawa
409 views
•
29 slides
JavaScriptで加速度・回転情報を取得してみた
iPride Co., Ltd.
332 views
•
9 slides
More Related Content
Slideshows for you
(20)
alieaters_tokyo_20200325_yoshimura
Masaki Yoshimura
•
591 views
tokyo.vcl発表資料(VarnishCache3.0新機能とVUPの仕方)
Iwana Chan
•
3.4K views
Varnishのログの眺め方
Iwana Chan
•
4.7K views
Stroustrup10章雑感
31 00
•
260 views
Openjdk 入門してみた話
Tokuhiro Matsuno
•
3.2K views
マスタリングJUNOS DHCP
ZenSekibe
•
75 views
RelaxCafe@CouchDB break.4
Yohei Sasaki
•
837 views
Varnish 4.0 Release Party in Tokyo発表資料
Iwana Chan
•
9.5K views
JavaScriptで位置情報を取得してみた
iPride Co., Ltd.
•
864 views
お金をかけないDBチューニング
Kazuya Sato
•
6.4K views
HUで6000万pvのトラフィックを捌くまでに起ったことをありのままに話すぜ
basicinc_dev
•
1.3K views
タイマー
TENTO_slide
•
311 views
Spockの基礎
Kiyotaka Oku
•
3.9K views
Aizu lt tokyo_luxion
Tomoaki Tamura
•
602 views
第8回KPF発表資料
cryks
•
4.3K views
Amazon lexを触ってみた
Yoichi Toyota
•
2.7K views
カジュアルにソースコードリーディング
Akihiro Okuno
•
6.9K views
mrubyのfiberを試してみた
Kindai University
•
981 views
LSTM
Cotty
•
134 views
Distributed processwithapex&flow lowcode
furuCRM株式会社 CEO/Dreamforce Vietnam Founder
•
555 views
Recently uploaded
(20)
办加拿大多伦多大学假文凭毕业证
JhhhfGffh
•
0 views
★可查可存档〖制作布克大学文凭证书毕业证〗
mmmm282537
•
2 views
★可查可存档〖制作奥克兰商学院文凭证书毕业证〗
tujjj
•
2 views
28西澳.pdf
dsadasd17
•
2 views
Data-Centric AI開発における データ生成の取り組み
Takeshi Suzuki
•
145 views
230216_AI技術共有会_園部.pdf
RyosukeSonobe
•
2 views
41布兰登大学.pdf
dsadasd17
•
2 views
☀️《UMB毕业证仿真》
hjhgg
•
0 views
무료스포츠중계 〔www,rtЗЗ,top〕코드 b77 플레이보이카지노 ㋁ 황제카지노 ㉤ 나미비아 국가경기 Ⓣ afc윔블던 ㈭ 퀴라소 ㈗ 축구...
ssusere9c2b4
•
5 views
★可查可存档〖制作巴黎第十二大大学文凭证书毕业证〗
tujjj
•
3 views
SPECIALIZED heavy racks.pdf
FernandoRivasCortes1
•
2 views
APM.pptx
SatishKotwal
•
2 views
★可查可存档〖制作温尼伯大学文凭证书毕业证〗
mmmm282537
•
3 views
★可查可存档〖制作密德萨斯大学文凭证书毕业证〗
vgfg1
•
2 views
☀️《UMKC毕业证仿真》
DFFFFG
•
0 views
204-杨百翰大学.pdf
fdhrtf
•
2 views
☀️《TRU毕业证仿真》
nhhh4
•
0 views
AI予約サービスのMLOps事例紹介
Takashi Suzuki
•
4 views
☀️《UIUC毕业证仿真》
hjhgg
•
0 views
#国外留学文凭购买Trent假毕业证书
fc2c0f2b1mymailol
•
2 views
Advertisement
リトライでtime.Sleepを使ったら積んだ話
1 リトライでtime.Sleep()使ったら積んだ話 mercari.go#14
2 名前: 田村弘(rossy) ● 経歴:
信州大学 → メルペイ(4月~) ● ポジション: バックエンド ● Go歴: 9ヶ月 ● 趣味: 筋トレ、読書 @rossy_0213 @rossy0213
3 何が起きたのか ● 新しいマイクロサービスのテストをしていました
4 何が起きたのか ● タイムアウトが結構の割合で発生していた
5 ● 実際どこで時間かかっていたかというと 調査
6 ● 実際どこで時間かかっていたかというと 調査
7 サービス間通信について ● タイムアウト付きのcontextを付けてリクエストしている
8 サービス間通信について ● timeout付きのcontextを付けてリクエストしている
9 リトライについて ● 一時的障害による失敗をカバーする ○ 例えば、ネットワークの損失、高負荷時による不調
10 リトライについて ● リクエストを少しでも早く返したい ○ 例えば、99%のリクエストが200msで終わり、残り1%が極端に遅 い場合、下図の仕組みを入れる
11 サービス間通信について ● サービスBでchildCtxを生成してリクエストをしている ○ context.WithTimeout(parentCtx,
time)でchildCtxを生成する
12 context.WithTimeout()について ● context.WithTimeout()の中身はcontext.WithDeadline() ○ 子contextのdeadlineは親のdeadlineより大きくなることはない contextのソースコード
13 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) }
14 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) } contextの有効性を確認する
15 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) } 実際の処理を行って、結果を代入する
16 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) } リトライ可能なエラーであるかを確認する
17 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) } 待機時間を計算して待機する
18 ● 実際どこで時間かかっていたかというと 調査
19 ● 実際どこで時間かかっていたかというと 調査
20 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) } 怪しい...
21 retryのコード(一部抜粋) for { select { case
<-ctx.Done(): // context.Cancel()類が呼び出されたエラーを返す return ctx.Err() default: } if err = fn(); err == nil { // リトライしたい処理を行う return nil // エラーがないなら処理終わり } if !bc.checkRetryable(err) { // retryできないエラーならエラーを返す、例えば、400番台 return err } n := bc.Next() // 回復を待つための待機時間を計算する time.Sleep(n) } 設定ミスにより、常に100s以上の待機時間が出力されていた
22 ● リトライ前の待機時間により処理時間が伸びる 障害ストーリー
23 ● 待機時間がサービスAのDeadlineを超える 障害ストーリー
24 ● Deadline以上の待機時間を算出できないようにする 解決策 Part1 func
(bc *backoffWithContext) Next() time.Duration { select { case <-bc.ctx.Done(): return Stop default: } next := bc.exponentialBackoff.Next() if deadline, ok := bc.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { return Stop } return next } 待機時間算出する前に contextの有効性を確認する
25 ● Deadline以上の待機時間を算出できないようにする 解決策 Part1 func
(bc *backoffWithContext) Next() time.Duration { select { case <-bc.ctx.Done(): return Stop default: } next := bc.exponentialBackoff.Next() if deadline, ok := bc.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { return Stop } return next } 待機完了の時間がDeadlineを越えていないことを確認する
26 ● context.Done()の検知とリトライ前の待機を両立させる ○ time.Timerを導入する ■
timeパッケージにあるありがたい関数 ■ 決められた時間にチャネルにイベントを送信する ● つまり、ctx.Done()イベントの受信と両立できる ○ 仕組み ■ 一つのゴルチーンで複数のタイマーを管理する ■ 複数のタイマーをヒープで管理して、一番近い時間までsleepし て、時間になったらチャネルにイベント送信する 解決策 Part2
27 ● time.Timerを使ったリトライ 解決策 Part2(コード一部抜粋) for
{ if err = fn(); err == nil { return nil } if !be.checkRetryable(err) { return err } if next = be.Next(); next == Stop { return err } t.Start(next) select { case <-ctx.Done(): return ctx.Err() case <-t.C(): } } 今まで通り
28 ● time.Timerを使ったリトライ 解決策 Part2(コード一部抜粋) for
{ if err = fn(); err == nil { return nil } if !be.checkRetryable(err) { return err } if next = be.Next(); next == Stop { return err } t.Start(next) select { case <-ctx.Done(): return ctx.Err() case <-t.C(): } } Stopだったらエラーをそのまま返 す
29 ● time.Timerを使ったリトライ 解決策 Part2(コード一部抜粋) for
{ if err = fn(); err == nil { return nil } if !be.checkRetryable(err) { return err } if next = be.Next(); next == Stop { return err } t.Start(next) select { case <-ctx.Done(): return ctx.Err() case <-t.C(): } } ctx.Done()と指定時間になること のどちらか先に発火する
30 ● 原因 ○ パラメータの設定ミス ○
time.Sleepによって、context.Done()が検知できなかった ● 根本対策 ○ Deadline以上の待機時間を算出できないようにする ○ timerでcontext.Done()の検知と待機を両立させる まとめ
31 ● https://github.com/rossy0213/retry ○ contextを扱うretryライブラリー ○
実例目的なので、機能はあまりない ○ ご意見、指摘、要望のissueお待ちしてます 今回のライブラリー例を公開してます
32 余談1 ● リトライの副作用 ○ 正しいレスポンスが帰ってこない可能性がある
33 余談1 ● 冪等性 ○ 同じリクエストなら何度しても同じ結果を返す
34 余談2 Retryについて記事を書きました - Software Design
9月号 - 作品で魅せるGoプログラミン グ - Goで作るRetryライブラリー - Retryの基礎とGoで実装する 方法 - amazon
35 ● リトライの基礎知識 ○ retry
patten(デザインパターン) ○ Exponential-backoff(待機時間の計算方法) ○ backoff-with-jitter(リトライを分散する手法) ○ How Do They Do It: Timers in Go (time.Timerの仕組み説明) ● ライブラリー ○ https://github.com/avast/retry-go ○ https://github.com/cenkalti/backoff (context扱うならおすすめ) ○ https://github.com/App-vNext/Polly ○ https://github.com/spring-projects/spring-retry ● トランザクション処理と冪等性 ○ マイクロサービスにおける決済トランザクション管理 参考
Advertisement