Slide 1

Slide 1 text

GoにおけるAPI Client 実装パターン Hisayuki Matsuki (@mtskhs) Go Conference 2019 Autumn

Slide 2

Slide 2 text

About me 松木久幸 @mtskhs Backend Engineer Gopher Dojo 1期生 2 Service ● EC @ NTT Resonant ● スポーツAI解説アプリ(SpoLive) @ NTT Communications Interest ● Agile (シリコンバレーで3ヶ月働いて 体感した自律型組織のススメ) https://speakerdeck.com/matsu0228/organizationtheory-of-engineering ● Agile Testing Days 2018 レポート https://speakerdeck.com/matsu0228/report-of-agiletestingdays2018

Slide 3

Slide 3 text

SpoLive 3

Slide 4

Slide 4 text

API Client マイクロサービスアーキテクチャによる開発が普及している現在、REST API におけるHTTPリクエスト処理が求められる場面は多い 4 https://microservices.io/

Slide 5

Slide 5 text

Bad Example of API Client ● `net/http` を使えば簡単?! 5 Sample API from https://noopschallenge.com

Slide 6

Slide 6 text

Bad Example of API Client 考えるべきこと 6 ● エラーコード(200 OK以外)が返 却されたら? ● ネットワークが一時的に切断され たら? ● 利用するAPIが複雑化(認証が追 加される・リクエストの種類増える 等)したら? ● `net/http` を使えば簡単?!

Slide 7

Slide 7 text

Contents 1. 重要な概念とGoにおける実装 1.1. エラー時のリトライ処理 1.2. 冪等性の担保 1.3. RequestOptionsを用いた汎用的な設計 2. よくある実装パターン 2.1. JSON decode pattern 2.2. 認証 2.3. Test設計 7 Sample Code : https://github.com/matsu0228/apiClientExample-GoConference2019Autumn

Slide 8

Slide 8 text

Error handling ● HTTP Status・レスポンスの内容 等に応じて、エラーをどう扱うべき か定義しておく ● リトライできるか・何も処理しない か etc 8

Slide 9

Slide 9 text

“Exponential Backoff エクスポネンシャルバックオフは、再試行間の待機時間を累進 的に長くして、連続的なエラー応答を受信するという考えに基づ いています。最大遅延間隔で最大回数の再試行を実行する必 要があります。再試行の最大遅延間隔と最大回数は必ずしも固 定値ではなく、実行する操作や局所的な要因 (ネットワークのレ イテンシーなど) に基づいて設定する必要があります。 9 Retrying https://docs.aws.amazon.com/ja_jp/general/latest/gr/api-retries.html

Slide 10

Slide 10 text

Retrying Exponential Backoff の考えに基づきリトライする効用 ● APIサーバー側からみて、Client数が増えたときにも捌ける Request数を最大化できる 10 https://aws.amazon.com/jp/blogs/architecture/exponential-backoff-and-jitter/

Slide 11

Slide 11 text

Retrying Exponential Backoff によるリトライの ライブラリ例: github.com/cenkalti/bac koff 11

Slide 12

Slide 12 text

Idempotency - 冪等性の担保 よくある事例 ● 100件のPOST通信のうち90件は成功・10件失敗した場合、 すでに処理済みのものを再度POSTしたら、処理済エラーが返却され てバッチがコケる ● サービスAへの処理は成功したが、サービスBへの処理は失敗した (RDBでいうトランザクション) 解決策 ● 手元で、処理IDと処理ステータスをもたせる ○ 成功した90件: 処理済 / 失敗の10件: 未処理のまま ○ サービスAは成功 / Bは未処理 (リトライ or Aの取り消し) 12

Slide 13

Slide 13 text

Highly scalable design - 汎用的な実装 ● request生成時に考えること ○ ドメインは初期設定 + リクエスト毎にURL Path設定 ○ 各リクエストに、共通のHeader追加 ○ リクエストごとに、固有のHeader追加 13

Slide 14

Slide 14 text

Highly scalable design - 汎用的な実装 Clientの実装 ● ドメイン設定 ● 共通Header 14

Slide 15

Slide 15 text

Highly scalable design - 汎用的な実装 Request生成 ● Method ● URL Path ● 個別Header 15

Slide 16

Slide 16 text

Highly scalable design - 汎用的な実装 各Requestでは差 分だけ設定すれ ばよい ● Method ● URL Path ● 個別Header 16

Slide 17

Slide 17 text

Contents 1. 重要な概念とGoにおける実装 1.1. エラー時のリトライ処理 1.2. 冪等性の担保 1.3. RequestOptionsを用いた汎用的な設計 2. よくある実装パターン 2.1. JSON decode pattern 2.2. 認証 2.3. Test設計 17 Sample Code : https://github.com/matsu0228/apiClientExample-GoConference2019Autumn

Slide 18

Slide 18 text

https://mholt.github.io/json-to-go/ 18 JSON decode pattern - Go Struct sampleデータから、GoのStructを生成する

Slide 19

Slide 19 text

19 JSON decode pattern - Decode よくある実装パターン: response.Bodyから構造体を生成する関数を用意 testableな実装を心がける。

Slide 20

Slide 20 text

20 JSON decode pattern - Delay parsing JSONがステータスに応じて構造が変化する場合、 “json.RawMessage” を利用し遅延評価する https://godoc.org/encoding/json#RawMessage

Slide 21

Slide 21 text

Authorization APIの要件にあった認証ヘッダの設定 e.g. アカウント毎に発行されたキーの base64エンコードしたものをヘッダに付与してアクセス。発行 キー”aabbcc:ddeecc”なら”Authorization: Basic YWFiYmNjOmRkZWVjYw==” 21

Slide 22

Slide 22 text

Testing strategy 課題:APIリクエストができる環境には制限がある API Clientに関するTest技法 ● interfaceとして切り出す(client全体をmock) ● httptest を用いたE2Eテスト ● Symmetric API Testingの概念 (レスポンスを保存しておく) 22

Slide 23

Slide 23 text

Testing strategy clientをinterfaceとして切り出しておくと、利用側のテストが容易に 23 usecase/main.go usecase/main_test.go

Slide 24

Slide 24 text

Testing strategy net/http/httptest を利用しlocalhost にAPIServerを立ち上げることによる E2Eテスト 24

Slide 25

Slide 25 text

Testing strategy “Symmetric API Testing” ● レスポンス結果をローカルディスクに保存 ● テストに上記ファイルを利用して試験(httptestレスポンスとして設定する等) 25 refer from: https://deeeet.com/writing/2016/10/25/go-interface-testing/

Slide 26

Slide 26 text

Testing strategy 26 refer from: https://deeeet.com/writing/2016/10/25/go-interface-testing/ “Symmetric API Testing” ● レスポンス結果をローカルディスクに保存 ● テストに上記ファイルを利用して試験(httptestレスポンスとして設定する等)

Slide 27

Slide 27 text

Summary API Clientの実装パターンを、サンプルコードと共に体系的に紹介 1. 重要な概念とGoにおける実装 ● エラー時のリトライ処理、冪等性の担保、 汎用的な設計 2. よくある実装パターン ● JSON decode pattern、認証、test技法 27 Sample Code : https://github.com/matsu0228/apiClientExample-GoConference2019Autumn

Slide 28

Slide 28 text

SpoLive - https://spo.live/ ラグビー国際試合に対応しました! 28