Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

クラウド環境下におけるAPIリトライ設計

199 views

Published on

PHPカンファレンス福岡2019での発表資料です

Published in: Technology
  • Be the first to comment

  • Be the first to like this

クラウド環境下におけるAPIリトライ設計

  1. 1. クラウド環境下における APIリトライ設計 PHPカンファレンス福岡2019 山田 幸司
  2. 2. 自己紹介 山田 幸司 / こ~じ Twitter: @koooxi Qiita: @koujiYamada 経歴:エンジニア歴18年、PHP歴12年、秀丸で開発したい秀丸er 趣味:ボードゲーム    (九州カタンクラブのシステム担当) 趣味で作っているもの カタン ダイスカウンター(PWA対応) https://catan-dice-counter.kojilabo.net/ 九州カタン王 大会サイト http://kyushu-catan.com/event_manager/
  3. 3. 今日のサマリー 1. 業務でどんなトラブルがあったのか 2. その時に決めたリトライポリシー 3. PHPで使えるリトライライブラリの紹介
  4. 4. 実際の業務で起きたトラブル
  5. 5. トラブルがあったシステムの簡単な構成説明 システム構成によっても前提が変わってくる 今回検討したシステム構成は以下の通り ● APIはAzureの仮想マシンにCakePHPで実装(nginx + php-fpm) ● DBは以前はIaaSで運用していたが、Azure Database for MySQLに乗り換えた ● フロントはAngularJSによるSPA
  6. 6. 起きたトラブルとその原因 IaaSで運用していたMySQLをAzureに乗り換えた所、サービスがフェイルオーバーによ る瞬断を起こすたびにAPIでエラーが発生 SaaSを使う場合に必要なリトライ処理がまともに考慮されていなかった というかIaaSでもリトライは正しく実装する必要はあるのだが、運よく予定メンテナンス以 外では落ちることがなかったので後回しになってた それがSaaSにしたことで表面化しただけ
  7. 7. 策定したリトライポリシー
  8. 8. リトライポリシー検討 ● SaaSに接続する部分ではリトライは必須とする ● ユーザ操作がトリガーであれば再操作を期待し、過度なリトライを行わない ○ 自動的なリトライが長すぎると、却って速度面で不満を生みかねない ○ DBの接続失敗などはAPI側でリトライするため、フロント側のリトライは最小限に ● APIのHTTPステータスコードによる柔軟なリトライも対応 ● APIコールのトリガーによってルールを変えれればなおベスト ○ タイマーやイベント起因の場合は暗黙のリトライがあったほうがよい ○ バッチ処理では長めのリトライを複数回行う
  9. 9. 策定したリトライポリシー ~API側~ API側の処理でリトライが必要な場合、エクスポネンシャルバックオフを採用する 一定回数リトライしても処理が復旧できなかった場合、レスポンスコード503を返し、後の 対応はクライアント側に任せる ただし、復旧不可能なエラーの場合リトライせずにレスポンスコード500を返す
  10. 10. 策定したリトライポリシー ~フロント側~ HTTPステータスコードが408、502、503、504の場合はリトライを行う (当初は5秒間隔で最大2回リトライを行う設定として、随時調整を行う) ● 408 Request Timeout ● 502 Bad Gateway ● 503 Service Unavailable ● 504 Gateway Timeout 選定基準はAPIサーバに処理が渡らずに中断されたか (例外として、503はAPI側で定めたポリシーに合わせてる)
  11. 11. 補足1:エクスポネンシャルバックオフとは リトライの仕組みの1つで、リトライ間隔を徐々に広げていくアルゴリズム 初回のリトライ間隔に係数を掛け、指数関数的にリトライ間隔を増加させる (1s⇒2s⇒4s⇒8s⇒…) SaaSなどを使うと、サービス都合による瞬断を起因としたエラーが発生する そのようなエラーは基本的には即座にリトライすることで回復することが多い しかし瞬断じゃない場合は短期間に何度もリトライしても回復する可能性は低い つまり、最初のほうは短い間隔でリトライしたほうがいいけど、何度も繰り返す場合は間 隔を長く取らないと無駄に試行回数が増えるという事情をいい具合に解消するための仕 組み
  12. 12. 補足2:リトライ判定の具体例(MySQL) Connect処理、およびSQL実行処理時にリトライを追加する 復旧可能/不可能判定はSQLエラーコードをもって行う 【MySQLのリトライ不要エラーコードの例】  SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'xxx' cannot be null  SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; ...  SQLSTATE[HY000]: General error: 1364 Field 'xxx' doesn't have a default value エラーコードの取得はPDOException::getCode()、およびPDOException::errorInfo[1]を 使うと便利
  13. 13. PHPで使えるリトライライブラリ
  14. 14. vkartaviy/retryのご紹介 今回PHPでエクスポネンシャルバックオフのアルゴリズムをもったライブラリを探してみ たところ、ほとんど選択肢*1 がない そんな中見つけたvkartaviy/retryの使い方を紹介したいと思います vkartaviy/retry 読み方:ロシア人名で、よくわからない(Vladimir Kartaviy) Github:https://github.com/vkartaviy/retry 開発状況:残念ながら最終更新が4年前なので停止してそう 余談:どうも別言語向けのライブラリを参考にしてそうだけど詳細不明 *1 みんな大好きGoogleのGoogle Cloud Client Library for PHPにも実装がある
  15. 15. vkartaviy/retryのサンプル vkartaviy/retryには公式リファレンスがなく、あるのは以下のようなサンプルのみ <?php use RetryRetryProxy; use RetryPolicySimpleRetryPolicy; use RetryBackOffExponentialBackOffPolicy; $retryPolicy = new SimpleRetryPolicy(3); $backOffPolicy = new ExponentialBackOffPolicy(); $proxy = new RetryProxy($retryPolicy, $backOffPolicy); $result = $proxy->call(function() { // call external service and return result });
  16. 16. vkartaviy/retryでできること 以下のパラメーターを指定できます ● 試行回数 ● リトライ間隔の初期値 ● リトライ間隔の増加係数 ● リトライ間隔の最大値 色々なルールでのリトライをサポートします ● リトライ間隔にランダム性を持たせる ● リトライさせない条件を定義できる ● 固定間隔、線形増加のBackOffPolicy
  17. 17. vkartaviy/retryのもう少し詳しい使い方 Qiitaの記事としてアップしてますので、ぜひ参考にしてください PHPでExponential Backoffを扱う
  18. 18. まとめ
  19. 19. まとめ ● SaaSを使う部分のリトライは必要(使わなくても本当は重要) ● ユーザ再操作が期待できるところは、あえてリトライしない選択も ● 複雑なリトライはできる限り既存のライブラリを使う ご清聴ありがとうございました!

×