これからの Microservices

20,941 views
20,467 views

Published on

DeNA TechCon 2016 の発表資料です。
REST と JSON の突っ込んだ話と、ちょっと Microservices の話。タイトルに偽りありです。

Published in: Technology

これからの Microservices

  1. 1. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. これからの Microservices DeNA TechCon 2016 January 29, 2016 Toru Yamaguchi Senior Architect Sub Business Unit Head Open Pla=orm Business Unit DeNA Co., Ltd.
  2. 2. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices とは何か これからの Microservices 2
  3. 3. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Monolithic Architecture !  Monolithic Architecture とは提供したい機能が単⼀のアプリケーショ ンで提供されているようなアーキテクチャのこと ⁃  世の中の Web アプリケーションはほとんどこれ 3 出典: http://microservices.io/patterns/monolithic.html
  4. 4. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Monolithic Architecture の利点 !  開発が簡単 ⁃  全ての機能が単⼀のアプリケーションの中にあるので、システム の全容が掴みやすい !  デプロイが簡単 ⁃  単⼀のアプリケーションをデプロイするのみでアプリケーション の更新が完了する !  スケールが簡単 ⁃  アプリケーションのプロセスを増やし、ロードバランシングする だけで基本的にはスケールアウトする !  但しこの利点は継続的に当てはまるかというと当てはまらない 4
  5. 5. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Monolithic はコードが肥⼤化し破綻しやすい !  提供するサービスが成⻑するに連れてコードベースも肥⼤化する ⁃  同じようなライブラリが複数出来てしまったり ⁃  コードの修正がどこまで影響するかが分からなくなってしまったり !  往々にしてこのような破綻は何をもたらすか ⁃  システムのキャッチアップに時間が掛かる ⁃  ⼤量にテストを書かないと安全性を担保出来ない ⁃  つまり開発スピードが著しく損なわれる 5
  6. 6. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Monolithic はデプロイに時間が掛かる !  どうしてデプロイに時間が掛かるか ⁃  全てのサービスを含んだアプリケーションなので、そのアプリケ ーションをスケールアウトするにはかなりのインスタンスが必要 になる ⁃  ⼀⽅でちょっとしたコードの修正を反映させたくても全てのイン スタンスに対してデプロイを⾏わねばならない !  デプロイに時間が掛かる弊害は何か ⁃  頻繁なデプロイが出来ないのは Continuous Deployment (CD) を難しくする ⁃  つまり、システムを最新に保つための粒度を細かく出来ず、デプ ロイの差分を⼤きくし、デプロイしてみないと何が起こるか分か らない 6
  7. 7. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Monolithic はスケールアップ/アウトさせにくい !  システムの特性により CPU やメモリ、I/O などに intensive な機能が ありえる ⁃  Monolithic だと機能ごとにそうした特徴がある場合に他の機能の 提供に影響を与えかねない ⁃  つまりスケールアップさせるのが難しくなる !  ロードバランシング + インスタンス追加だけではいつまでもスケール アウトさせる事が出来ない ⁃  データベースなども追従してスケールアウトさせる必要がある ⁃  またアプリケーションインスタンスが多くなるとデータベース等 との永続接続も難しくなっていく •  というか事実上出来なくなる 7
  8. 8. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Monolithic ApplicaJon と Database !  上記の図のようにモジュールが増えて、依存するデータベースが増え ると持つべきコネクション数が増える ⁃  結果ローカルポートの数も有限なので、永続接続出来ない 8 User Module Friend Module Notification Module User DB Friend DB Notification DB プロセス モジュールの量とデータベースの数が増えてスケールアウトの 為にインスタンスを追加すると、ここのバリエーションが増え る
  9. 9. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 9 そこで Microservice Architecture を使う
  10. 10. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices Architecture !  Microservices では機能をサービスという⼩さなコンポーネント単位 に分割するアーキテクチャ !  2014年頃から急速に注⽬されるアーキテクチャになってきた 10 出典: http://microservices.io/patterns/monolithic.html
  11. 11. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices Architecture の利点 !  個々の Microservices は⼩さくなる ⁃  つまり開発が容易で、アプリケーションコンテナの起動も早い !  個々の Microservices のデプロイは独⽴して⾏える ⁃  つまり頻繁に新しいバージョンのコンテナをデプロイ出来る ⁃  個々のサービスを独⽴して開発していけるので複数のチームが独 ⽴して動く事が出来る !  障害耐性を向上させる ⁃  仮に1つのサービスがメモリリークなどを起こしても全てのサー ビスがダウンする訳ではない !  ⼀瞬良い事尽くめのように⾒えますが、もちろん悪い点もあります ⁃  ただこの辺のテーマは既に多くの⼈が語っている所なので今回は割 愛 11
  12. 12. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices Architecture で必要なこと !  サービスエンドポイントとのメッセージ通信 ⁃  HTTP 経由か MQ を通じたメッセージング !  サービスエンドポイントとのメッセージプロトコル ⁃  REST !  分散ガバナンス・分散データ管理 ⁃  サービスごとにコンポーネントのプログラミング⾔語を選択出来る ⁃  データベースを独⾃に持ちサービス間で共有しない !  インフラストラクチャの⾃動化 ⁃  CI/CD, II !  等々 12
  13. 13. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 今⽇の本題 !  Microservices への取り組みは我々も2013年くらいから取り組み始め ています !  今⽇はそうした経験も踏まえて Microservices の今後について、個⼈ 的に思っている事を以下のテーマに基づきお話させて頂きます ⁃  REST ⁃  Microservices !  あんまりまとまりが無いので、気楽に聞いて下さい! 13
  14. 14. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. REST これからの Microservices 14
  15. 15. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. REST !  Microservices でのメッセージプロトコルに⽤いられるプロトコルの 主流は REST です ⁃  REST の設計⼿法が ROA (Resource Oriented Architecture) !  ROA には4つの概念と4つの特徴がある 15
  16. 16. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ROA の4つの概念 !  Resource ⁃  データとして表現出来るもの ⁃  識別⼦として URI を持つ !  URI ⁃  リソースの所在を指し⽰す識別⼦ !  Representation (表現) ⁃  リソースのデータを表現する形式 •  JSON/XML など !  Link ⁃  リソース間の関連を URI で表現した物 16
  17. 17. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ROA の4つの特徴 !  Addressability (アドレス可能性) ⁃  URI によってリソースを指し⽰す事が出来る !  Unified Interface (統⼀インターフェース) ⁃  HTTP メソッド •  GET/POST/PUT/DELETE など •  安全性/ベキ等性/キャッシュ可能 ⁃  HTTP の標準的な語彙によるアクセス •  Content Negotiation, Conditional Request !  Stateless (ステートレス性) ⁃  サーバーがクライアントアプリケーションの状態を持たない •  OAuth 2.0 の Bearer Token や Basic Authentication など !  Connectedness (接続性) ⁃  URI によるリンク、ハイパーメディア •  HAL/Collection+JSON/JSON-LD など 17
  18. 18. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 18 REST は⼈々を幸せにしたか?
  19. 19. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. REST は制約 !  従って全ての現実的な課題に応えるのは困難 !  URI は⼀次元のデータ構造 ⁃  あるユーザーに届いた通知 •  /users{/userId}/notifications ⁃  全ての通知 •  /notifications !  現実の操作は Unified Interface に収まりきらない ⁃  Overload GET/POST や Algorithm Resource を避ける事が出来な い •  POST /users/leaderboards{/leaderboardId}/score/incr 19
  20. 20. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 20 PUT と PATCH、 ParHal Updates
  21. 21. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. PUT は使えるか !  PUT は対象リソースの状態が作成される、または変更されるリクエス トである ⁃  4.3.4. PUT - RFC7231 ⁃  レスポンスは原則としてその対象リソースに GET した表現が返 って来る ⁃  従ってリクエストは暗黙のデフォルトフィールド以外は完全な表 現が求められると考えられる !  作成の⽤途は別に POST でも構わない ⁃  POST /articles ⁃  POST /articles{/id} は PUT /articles{/id} と同等 !  変更は概ね部分的 (Partial Updates) である ⁃  つまり PUT より PATCH の⽤途の⽅が多い ⁃  Partial Updates には幾つか考え⽅がある 21
  22. 22. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ParJal Updates (PUT と垂直分割されたリソース) !  対象リソースの属性を絞り込むフィルタ(例では fields パラメータ)を 指定して、リクエストに完全な表現を送り込む ⁃  OpenSocial で提供されていた機能 !  元々の PUT の要件を守ろうとするとこんな感じになってしまう 22 PUT /resources{/id}?fields=state,description HTTP/1.1 Authorization: Bearer eyj… Content-Type: application/json { "state": "REJECTED" }
  23. 23. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ParJal Updates (PATCH と JSON Merge Patch) !  JSON Merge Patch (RFC 7396) を⽤いて PATCH する ⁃  Content-Type が application/merge-patch+json ⁃  上記の例だと state の差し替えと description の削除を表す !  ほとんどのユースケースで問題は無い ⁃  但し細かい操作は出来ない (上書きと削除のみ) 23 PUT /resources{/id} HTTP/1.1 Authorization: Bearer eyj… Content-Type: application/merge-patch+json { "state": "REJECTED", "description": null }
  24. 24. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ParJal Updates (PATCH と JSON Patch) !  JSON Patch (RFC6902) を⽤いて PATCH する ⁃  Content-Type が application/json-patch+json !  JSON Merge Patch に⽐べるとだいぶ便利 ⁃  それでも出来ない操作が多々ある 24 PUT /resources{/id} HTTP/1.1 Authorization: Bearer eyj… Content-Type: application/json-patch+json [ { "op": "replace", "path": "/state", "value": "REJECTED" }, { "op": "remove", "path": "/description" } ]
  25. 25. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Patch の利点 !  現状では JSON Patch を⽤いるのが⼀番良いかなと思っています !  JSON Schema による validation を記述するのが⽐較的容易 !  事前にリソースの状態を知らなくても⾼度な PATCH が出来る ⁃  add による object や array への属性や要素の追加・変更や挿⼊ ⁃  replace による存在確認つき変更 ⁃  move/copy による移動や複製 ⁃  test による条件付き更新 !  但し出来ない事も多い !  Since the RFC was published, a number of users and implementers have stepped forward, saying roughly "this is great, but..." ⁃  https://github.com/json-patch/json-patch2 ⁃  既に改善していこうという動き⾃体はあります 25
  26. 26. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Patch の⽋点 !  operator が⾜りない、ないしは⼒不⾜ ⁃  例えば 数値に対する Increment/Decrement は事前に状態を知 らないと出来ない操作の代表例 ⁃  従ってケースによっては Conditional Request と併⽤しないと安 全な操作とならない !  test が貧弱 ⁃  あるポインタの値に対する完全⼀致のみサポート •  ポインタの有無をベースにしたオペレータなどが提案されていたりします ⁃  出来れば不等号なり様々な評価を使いたい所 !  データベースとの統合が⾯倒 ⁃  変更箇所はポインタで⽰されるが、データベースの定義との関連 を素直に記述出来るとは限らない 26
  27. 27. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Patch とデータベースの統合 (1) !  例えば MySQL 5.7.8 よりサポートされた JSON 型を⽤いて雑に管理 すると上⼿く⾏くのではないか ⁃  MySQL の JSON 型をドキュメント指向データベースとみなす !  コンセプト ⁃  変更可能な属性は JSON 型(object)で格納する •  例えば data みたいなカラムに⼊れてしまう •  id だとか createdAt, updatedAt のようなサーバーが割り当てる値は readOnly として扱う ⁃  JSON Patch は⼀度 SELECT FOR UPDATE で data カラムを取 得してからプログラム上で適⽤する 27
  28. 28. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Patch とデータベースの統合 (2) !  上記の例くらいに雑にテーブル設計する !  必要に応じて Virtual Generated Columns を使う 28 CREATE TABLE IF NOT EXISTS resources ( id bigint(20) unsigned not null, etag_version smallint(5) unsigned not null, data JSON, created_at int(10) unsigned not null, updated_at int(10) unsigned not null, PRIMARY KEY (id) ) ENGINE=InnoDB;
  29. 29. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 29 Content NegoHaHon と CondiHonal Request
  30. 30. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Content NegoJaJon とは何か !  レスポンスコンテンツに対する取得の仕⽅に対する事前の交渉 !  取得の仕⽅とは何か ⁃  表現⽅法 (メディアタイプ) •  Accept ヘッダ ⁃  キャラクタセット •  Accept-Charset ⁃  エンコーディング •  Accept-Encoding ⁃  ⾔語 •  Accept-Language !  上記のうち REST で最も表現しづらい、取り扱いづらいのが⾔語 30
  31. 31. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 多⾔語表現と REST に潜む罠 !  そもそも多⾔語表現をどのように取り扱うか ⁃  そもそも多⾔語対応するべき属性は string のみ •  但し全てが多⾔語対応するべき属性ではない •  つまり、作成時に全ての⾔語に対応出来ている属性とそうではない属性が 存在し得る ⁃  ⼀度に複数の⾔語分のリソースをどう作成するか •  特殊な表現とするのか !  ネゴシエーションの結果存在しない⾔語タグの場合の挙動をどうするか ⁃  GET はなるべく近い表現を返してあげたい? ⁃  POST/PATCH 等のオペレーションではサポートしている⾔語タ グ以外はリジェクトしたい? 31
  32. 32. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 多⾔語表現 – OAuth 2.0 Dynamic Client RegistraJon の例 !  OAuth 2.0 の dyn-reg (RFC7591) での多⾔語対応はある意味分かり やすい ⁃  ⾔語タグを明⽰したい場合は "#" 以下に指定して区別する ⁃  デフォルト値と同じデータ型として取り扱える !  ⽋点としては以下が挙げられる ⁃  サポートする⾔語タグ数分、フィールドが増える ⁃  Content Negotiation で ja を要求した場合、/name の値はどう なるのかが不定?(少なくとも Spec には書いてなさそう) 32 { "name": "Toru Yamaguchi", "name#en": "Toru Yamaguchi", "name#ja": "山口 徹" }
  33. 33. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 多⾔語表現 – Google JSON Style Guide の例 !  Google JSON Style Guide の data.lang を⽤いる !  メンバーリソースであってもコレクション形式での表現になる !  ⽋点としては以下が挙げられる ⁃  サポートする⾔語数分、多⾔語対応しなくて良いフィールドの冗 ⻑さが増す ⁃  ⾔語表現を端的に取得しづらい (array なので) 33 { "items": [ { "lang": "en", "name": "Toru Yamaguchi" }, { "lang": "ja": "name": "山口 徹" } ] }
  34. 34. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 多⾔語表現に銀の弾丸は無さそう !  実は弊社で最近やっているプロジェクトでは、これらとは全然違うフ ォーマットを適⽤してみました ⁃  個⼈的には凄く失敗だったと多いに反省している所です ⁃  今振り返ると dyn-reg 案が⼀番良かったと思っています !  いずれにせよ要件を挙げ、それらに対してどういう仕様にしていくか ⁃  要件を事前に洗い出せるかが肝要 34
  35. 35. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. (閑話休題) Google JSON Style Guide は⼀⾒の価値あり !  予約語の部分が特に⾯⽩い ⁃  data.lang (Content-Language 相当) だけでなく data.etag (ETag 相当), data.updated (Last-Modified 相当) など後述する Conditional Request に⽤いるであろう予約語が存在する •  特に ETag 値は gzip 圧縮をフロントの nginx にやらせると勝⼿に書き換 えるので、Content の部分でも記述するのが望ましいです !  他にも⾊んな事がガイドライン化されています ⁃  命名ルール ⁃  リンク ⁃  ページング ⁃  順序 •  ストリーミング処理を意識している模様 35
  36. 36. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. CondiJonal Request とは何か !  条件付きリクエストの事です ⁃  ある条件を満たしたとき or 満たさないときにリクエストが成⽴す る !  条件に使える Validator は以下 ⁃  Last-Modified ⁃  ETag (Weak/Strong) !  REST の⽂脈でより有⽤なのは ETag ⁃  If-Non-Match: "xyzzy" で最新のドキュメントを取得 ⁃  If-Match: "xyzzy" で楽観的ロックによるドキュメントの更新 ⁃  If-Non-Match: "*" で duplicated なエンティティの作成を抑⽌す る •  lost update 問題 36
  37. 37. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ETag と CollecJon Resource !  通常は Member Resource (Collection 中の各アイテム) について ETag を⽤いるのがスタンダード ⁃  これを Collection Resource にも適⽤する !  Collection Resource とは何か ⁃  Member Resource を包含する Resource の事 ⁃  Collection Resource の状態が変更になったら ETag の値も書き 換わる !  Collection Resource の状態とは何か ⁃  包含する Member Resource の追加・変更・削除のこと !  何に使うか ⁃  Collection への差分の有無を PULL 型で提供する ⁃  もしクライアントに差分更新をさせたいのであれば Member Resource の削除をインターフェースとして論理削除として表現 するか、内部データだけ論理削除とし削除済みのリソースも取得 出来るようにするか 37
  38. 38. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 38 JSON Schema と JSON Hyper Schema
  39. 39. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Schema とは何か !  JSON に対してデータ定義を与えるスキーマ⽂書の事です ⁃  http://json-schema.org/ !  JSON Schema 単体を指す場合は core, validation の事を指します ⁃  JSON Hyper Schema は hyper-schema を加えた概念 ⁃  core のバージョンで区別する。現在は draft-04 !  JSON Schema ⾃体、JSON で記述します ⁃  そして self descriptive です 39
  40. 40. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Schema の例 !  データ構造の定義を書く事が出来る !  例 ⁃  データ構造は JSON object である ⁃  id, name という属性を持ち、それぞれ⽂字列型である 40 { "id": "http://example.com/1.0.0/person.json", "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" } } }
  41. 41. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Hyper Schema とは何か !  Hyper は Hypermedia のこと ⁃  JSON を Hypermedia として扱う試みの⼀環 ⁃  具体的には Resource のデータ構造だけでなく Resource の挙動 や関連を指し⽰す為の枠組み !  具体的にはどうなっているか ⁃  JSON Schema の拡張になっている •  つまり JSON Schema で出来る事は JSON Hyper Schema でも出来る ⁃  出来る事は Link Description Object を列挙すること !  何に使えるか ⁃  事業者間での合意⽂書 ⁃  API のスケルトン・テストのひな形作成や API のバリデーション 41
  42. 42. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. JSON Hyper Schema の例 !  リソースのデータ構造に基づいた Link を列挙する事が出来る ⁃  /links の各要素が Link Description Object 42 { "id": "http://example.com/1.0.0/person.json", "$schema": "http://json-schema.org/draft-04/hyper-schema#", (中略), "links": [ { "method": "GET", "rel": "instances", "href": "/persons", "encType": "application/x-www-form-urlencoded", "mediaType": "application/json" }, … ] }
  43. 43. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ここが変だよ JSON Hyper Schema !  readOnly 属性 ⁃  変更不可な属性を指し⽰すメタデータ •  つまり PUT や PATCH による変更が出来ないという意味 •  POST 時には指定可能とも⾔える ⁃  つまり POST 時に仮に指定しなければならない属性の場合は POST と PUT で validation ルールが異なる !  href に対する謎のプリプロセス ⁃  ⽤途としてはリソースが JSON object 以外のケースの際に URI Template の変数に代⼊する為の仕組み •  string, array などを考慮している •  正直要らない !  続いて実⽤上凄く困る点について幾つかご紹介します 43
  44. 44. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. href での Template 変数 !  URI Template 中の変数は指し⽰すリソースのトップレベルのフィー ルドで表現しなければならない ⁃  /friend/id みたいなネストしたフィールド値は使えない ⁃  但しこの辺は draft-05 で直りそうです 44 { "id": "http://example.com/1.0.0/person.json", "$schema": "http://json-schema.org/draft-04/hyper-schema#", (中略), "links": [ { "method": "GET", "rel": "self", "href": "/users{/id}/friends{/friendId}", "encType": "application/x-www-form-urlencoded", "mediaType": "application/json" }, … ] }
  45. 45. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. schema の意味がメソッドごとに異なる !  schema はリクエストに対する制約を記述するキーワードです !  schema の解釈は以下です ⁃  GET や HEAD のようにリクエストボディが存在しない場合はク エリストリングの制約を表現する ⁃  それ以外はリクエストボディを意味する !  POST などに使える共通のリクエストパラメータは Hyper Schema に記述する事が出来ない 45
  46. 46. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices これからの Microservices 46
  47. 47. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 47 Bluk Process for Specified Resource
  48. 48. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 単⼀リソースに対する Bulk 処理 !  例えば以下のような物を指します ⁃  ⼀度に複数のメンバーリソースを作成したい ⁃  条件に合致するリソース全てを同⼀条件で変更したい ⁃  条件に合致するリソース全てを削除したい !  あまりこの⼿の要求に対する標準的なアプローチは⾒かけない ⁃  JSON API の Bulk Extension が参考になる !  JSON API の Bulk Extension は意欲的だかいけてない ⁃  PATCH の適⽤が Merge のみ ⁃  DELETE メソッドなのにリクエストボディが必要 48
  49. 49. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Bulk 処理はこうあるべき !  まず条件に合致するリソースを表現するようなリクエストパラメータ を定義すべき ⁃  ?filter.id.$in=aaa,bbb,ccc みたいな感じ !  POST の際はコレクションリソースに対して作成したいメンバーリソ ース全てを含んだコレクションリソースを作成すると、作成出来たメ ンバーリソースを含んだコレクションリソースが返る ⁃  INSERT INTO resources(...) VALUES (...), (...), ... !  PATCH の際は上記のフィルタをコレクションリソースに適⽤し、リク エストボディに JSON Patch を適⽤する ⁃  UPDATE resources SET ... WHERE id IN (…) !  DELETE は上記のフィルタをコレクションリソースに適⽤するのみ ⁃  DELETE FROM resources WHERE id IN (...) 49
  50. 50. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Bulk 処理 - POST !  コレクションに対してコレクションで応答する 50 POST /resources HTTP/1.1 Content-Type: application/json { "items": [ { "name": "foo" }, { "name": "bar" } ] } HTTP/1.1 201 Created Content-Type: application/json { "items": [ { "id": "aaa", "name": "foo" }, { "id": "bbb", "name": "bar" } ] }
  51. 51. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Bulk 処理 - PATCH !  条件に合致したリソース全てに同⼀の JSON Patch が適⽤される ⁃  異なる JSON Patch をそれぞれにリソースに割り当てたいという ユースケースは Bulk 処理として実現するのは困難 51 PATCH /resources?filter.id. $in=aaa,bbb HTTP/1.1 Content-Type: application/json- patch+json [ { "op": "add", "path": "/ description", "value": "blah blah" } ] HTTP/1.1 200 OK Content-Type: application/json { "items": [ { "id": "aaa", "name": "foo", "description": "blah blah" }, { "id": "bbb", "name": "bar", "description": "blah blah" } ] }
  52. 52. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Bulk 処理は標準装備すべき !  更新系の処理があるコンポーネントの共通仕様とすると便利 ⁃  特に実際にやる処理は個々にやる処理を並べただけの単純な処理 ⁃  しかもそれらを単⼀の DB トランザクションとしてアトミックな 処理に簡単に出来るはず 52
  53. 53. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 53 TransacHon and Resource Modeling
  54. 54. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. REST における分散トランザクションの実現は困難 !  やり⽅としては概ね⼆通りになる ⁃  ⼆相コミット (Two-Phase Commit) ⁃  ロングランニングトランザクション !  いずれの⼿法もきちんとやるのは難しい ⁃  Microservices においてサービスごとに参照する DB を分けてい るようなアーキテクチャを取る場合は、DB での⼆相コミットは 利⽤出来ない •  従ってコーディネータとなるようなリソースを作って⾃前で似たような処 理を作る必要がある ⁃  ロングランニングトランザクションの場合は補償トランザクショ ンを上⼿く設計する必要がある !  つまり Microservices における⼀つの指針として、トランザクション という概念を持つ処理の表現でリソースを細分化し過ぎると⾟い思い をする 54
  55. 55. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 分散トランザクションとリソースモデリング !  まずトランザクションで守らなければならない対象の堅牢性をどこま で求められるかを考慮すべき ⁃  決済系処理などは代表すべき対象 !  リトライ時の冪等性の担保をサービスが⼀部担うべきかクライアント が全⾯的に担うべきかは上記によって変わって来る !  サービスが担うべき場合はコーディネータとなるトランザクションリ ソースをきちんと設計する 55
  56. 56. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 56 API Gateway
  57. 57. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. API Gateway とは何か !  API Client と Microservices ののりしろとなる役割のコンポーネント ⁃  API Gateway には多数の機能が求められる 57 API Gateway REST REST REST MQ Service Service Service Client Client REST
  58. 58. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. API Gateway に求められること !  Client が Service の中⾝を知らなくても良いようにする ⁃  例えばある公開 API の中⾝がどのようなサービスを組み合わせて 提供されているかについて、Client は知らなくて良いような状態 にする ⁃  Service インスタンスの所在なども隠蔽化する !  Client 向けの公開 API の提供 ⁃  つまり場合によっては内部の Service のインターフェースと公開 インターフェースの翻訳を担う !  Batch Request/Response の提供 ⁃  複数の API 呼び出しを⼀度のリクエストで処理し、⼀つのレスポ ンスとして返す •  ネットワークラウンドトリップの削減のため •  HTTP/2 のコンテキストでは最適解ではない?(Server Push) 58
  59. 59. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. さらに API Gateway に求められる(かもしれない)こと !  セッションに ID を割り当てる事 ⁃  ここではセッションとは Client がリクエストして、レスポンスを 受けとるまでの間の事と定義します ⁃  セッション ID は何に使うか •  セッションごとに管理したいログ •  セッションの⽣存期間内で有効なキャッシュ !  ⾼度なメッセージング ⁃  Backend に対して Request-Reply 以外のメッセージングを適⽤す る •  Event Message (いわゆる PubSub 的な⽤途) •  Return Address (バックエンドが Server ではなく Worker を許容する モデル) ⁃  今⽇は時間の都合で割愛 59
  60. 60. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. セッション ID と分散トレーシング !  メッセージの req/res 時点での src/desc や時刻を記載してログに記 録してかき集める ⁃  その際に同⼀のセッション ID を割り当てる ⁃  ZipKin が有名 60 API Gateway 1 2 3 4 5 6 8 9 10 7 11
  61. 61. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. セッション ID とキャッシュ (1) !  各サービスは別のサービス呼び出しに対してキャッシュ可能なメソッド (GET など)による呼び出しを⾏う際に、セッションごとに消滅する Cache Service にセッション ID を使って問い合わせる ⁃  無ければ実際に Service C を呼び出す 61 API Gateway (1) Service A 呼び出し Session Cache Service Service A Service B Service C (2) Service B 呼び出し (3) Service C のキャッシ ュ呼び出し (4) Service C 呼び出し
  62. 62. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. セッション ID とキャッシュ (2) !  Service A は Service C への呼び出しがキャッシュ可能なメソッドに よって⾏われた場合はセッション ID と共に Cache Service に保存する 62 API Gateway (1) Service A 呼び出し Session Cache Service Service A Service B Service C (2) Service B 呼び出し (5) Service C のキャッシ ュ保存
  63. 63. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. セッション ID とキャッシュ (3) !  同⼀セッション内で Service C への同⼀呼び出しがキャッシュに存在 する場合は Service B は Service C を呼び出さなくても構わない 63 API Gateway (1) Service A 呼び出し Session Cache Service Service A Service B Service C (2) Service B 呼び出し (6) Service C のキャッシ ュ呼び出し
  64. 64. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. セッション ID とキャッシュ (4) !  API Gateway はセッションのレスポンスを返すに⼗分なレスポンスを 各サービスから収集した後に、セッションキャッシュを破棄する 64 API Gateway (7) Service A のレスポン ス Session Cache Service Service A Service B Service C (8) Service B のレスポン ス (8) セッションキ ャッシュの破 棄リクエスト
  65. 65. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. セッション ID とキャッシュ (5) !  同⼀セッションの中で異なるコンポーネントが同じリソースを「参照 」した際に Entity Tag が変わっているケースが原理上あり得る ⁃  セッション中に誰かが変更したとか !  こうした場合に、巡り巡って状態の異なるリソースに依存したレスポ ンスを返す⽻⽬になるのは宜しく無い ⁃  従って最も早くそのリソースにアクセスしたセッション中のコン ポーネントが Cache Service にそのリソースのスナップショット を保存しておくアプローチで上⼿く⾏くのではないか •  この際に Mutex みたいな物を⽤意しておかないと Race Condition が発 ⽣しうる 65
  66. 66. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 66 Access Token
  67. 67. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices と Access Token の相性が悪い件 !  Microservices はサービスごとに独⽴したインスタンスや DB を持ち、 API をインターフェースとして結合する Thin なやり⽅ ⁃  そのようなケースで Token DB をどう参照するのか? 67 AuthZ Server Token DB Client Resource Server Token Endpoint 1. Token Request 3. Token Response 2. Store Token 4. Request to Resource Server 異なるネットワークにある Token DB をどう参照するか?
  68. 68. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. OAuth 2.0 Token IntrospecJon (RFC 7662) !  Introspection Endpoint で Access Token の検証を AuthZ Server に依頼する事が出来る ⁃  これで⼀応 Microservices にも対応出来るようになる 68 AuthZ Server Token DB Client Resource Server Token Endpoint 1. Token Request 3. Token Response 2. Store Token 6. Lookup Token 4. Request to Resource Server IntrospecHon Endpoint 5. IntrospecHon Request 7. IntrospecHon Response
  69. 69. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. IntrospecJon API の課題点 !  アーキテクチャにも依るが、API Gateway 以下でも Access Token をその まま通過させて、各 Service へのリクエストにした場合、厳密には Service ごとに Access Token の検証が必要であろう ⁃  速度重視の API に不要なラウンドトリップが発⽣する ⁃  つまり⼤規模な Microservices に対して、採⽤を躊躇わざるを得ない !  ⼀つの解決策として API Gateway のみ Introspection Endpoint を使うと なりそう 69 Client API Gateway API (1) API (3) API (2) 1. API Request 2. 3. 4. 5.
  70. 70. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Access Token に JWT を使う !  Access Token は exp を迎える前に revoke さえされければ、 Resource Server でのアルゴリズム的な検証のみで良い ⁃  また /_ext/st は Scope Token (どんな権限があるか) 70 (注意) 実際の Mobage Connect の Access Token と⼀部フォーマットが異なります
  71. 71. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Subscribe Endpoint !  Access Token が revoke された場合に Resource Server 側に通知出来る 仕組みを作れば良い ⁃  他にも AuthZ Server のログインセッションが切れたら session_state を伝搬させるなど汎⽤的な PubSub があったら便利だと思われる 71 AuthZ Server Token DB Client Resource Server Revoke Endpoint 1. Revoke Request 4. Revoke Response 2. Remove Token Subscribe Endpoint Revoke Token Subscriber Endpoint 3. Publish Revoke Event 事前に Subscribe Endpoint で Revoke Event を subscribe するための URL を登録しておく
  72. 72. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Revoke Event の伝搬 !  上記のようなシステムを組む事で Revoke された Access Token の jti 値などを伝搬させて、Revoke 情報のみを各 Service に伝える ⁃  すうする事により、API は local 通信で revoke された Access Token かどうかを確認出来るようになる 72 API Revoked Token DB (Redis) Service API Revoked Token DB (Redis) Service Revoked Token Publisher (Redis) Revoke Token Subscriber Endpoint AuthZ Server 1. Publish Token Revoked Event 2. Publish to channel Subscribe channel Lookup token (localhost) Lookup token (localhost)
  73. 73. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Revoke された Token 情報の保持期間 !  revoke された jti だけ有効期限を迎えるまで、各 Service の Redis で持てば良い ⁃  それ以降は exp ⾒るだけで判断が付くため 73 Access Token (JWT) の有効期限 Cache に revoke された JWT の jH 値を格納する 発⾏ Revoke iat exp
  74. 74. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Conclusion これからの Microservices 74
  75. 75. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. REST !  REST はもっともマシでもっとも苦痛な解決策 ⁃  シンプルなだけに奥が深い !  世の中のオープン仕様だけで堅牢なインターフェースは作れない ⁃  基本は HTTP/ROA のセマンティクスで極⼒済ませる ⁃  まだまだ、独⾃に整備していかねばならない !  JSON Schema は draft-05 に期待したい ⁃  よりましになる 75
  76. 76. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Microservices !  コンセプトは良し ⁃  但し誰しもがやるべき事ではない •  ⼀定規模のサービス、⼈員など勘案して決めるべき !  普通に作るとインフラコストが増⼤し、処理速度も遅くなる ⁃  サービスの配備の仕⽅(Host/VM/Container) ⁃  ネットワークラウンドトリップを如何に少なくするか •  この辺は AWS/GCP が汎⽤的に解決するような問題ではないと思う ⁃  などなど !  まだまだ経験値が貯まっていない領域なので技術発展が⾒込まれる領 域だと思います ⁃  今なら挑戦しがいがある! 76
  77. 77. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Thanks !  ご清聴ありがとうございました 77

×