Slide 1

Slide 1 text

Lecture course on Microservices 第1部:マイクロサービスの全体像 中井悦司 / Etsuji Nakai 2023/01/23 ver2.2

Slide 2

Slide 2 text

参考資料 2 マイクロサービスの 全体像を把握するのに 最適 マイクロサービスの 「パターン」を網羅した 辞書的な本 適切な実装パターンを 選ぶための考え方 (トレードオフ)を解説 モノリスからマイクロ サービスへの移行に関連 したテクニックを解説 マイクロサービスにおけ るセキュリティと信頼性 に関する話題を提供 https://enakai00.hatenablog.com/entry/2022/05/04/213850

Slide 3

Slide 3 text

Contents ● 1. マイクロサービスの特徴 ● 2. マイクロサービスのライフサイクル ● 3. マイクロサービスの設計方針 ● 4. マイクロサービスのアーキテクチャー 3

Slide 4

Slide 4 text

1. マイクロサービスの特徴

Slide 5

Slide 5 text

アーキテクチャー = 建築設計? ● マイクロサービスが目指すソフトウェアアーキテクチャーは、「ビル建築」ではなく、 「都市計画」に近いと考えられる 5 By The original uploader was MarianZubak at English Wikipedia. - Transferred from en.wikipedia to Commons., CC BY 2.5, https://commons.wikimedia.org/w/index.php?curid=3402935 By Dudva - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=25441424 vs

Slide 6

Slide 6 text

変化に追従するための基本原則 ● 変更要求に対する凝縮度を上げることが「モジュール化」の基本 ○ 変更する理由が同じものは集める → 単一のモジュールだけを考えればよい ○ 変更する理由が異なるものは分離する → 想定外の影響を心配しなくてよい ● 開発者の認知能力を超えた連鎖的変更を防止。「容易に理解できる」範囲の変更 は生産性が高い 6 単一責任の原則 ↓ クラスを変更する理由は1つ以上存在してはならない

Slide 7

Slide 7 text

マイクロサービスがなぜ必要か? ● モノリシックなソフトウェアを継続的に機能拡張すると、コードが複雑になりすぎて、機能 追加が困難になる(時間とコストが掛かるようになる)。 ○ 追加したい機能に対して、修正すべき部分を網羅的に洗い出すことが困難になる。 ● 単一機能を提供する自律的で疎結合な「サービス」を組み合わせる事で、継続的な機能追加 ・機能拡張を容易に保つことを目指す。 ○ コードの変更だけではなく、本番環境への展開を含めた CI/CD パイプラインの設計が あわせて必要。  ⇨ これを実現するには、マイクロサービスは具体的にどのような特徴・特性を持つべきか? 7

Slide 8

Slide 8 text

マイクロサービスの具体例(オンライン投資サービス) 8 ● ユーザーが、株の売却リクエストを 出した場合の処理の流れ サービス手数料を 計算・引き落とし Order service A 社の株を 100 株売却 Stock transaction service 売却リクエストの 情報を記録 Order database Transaction database Fee service Fee rules database Market service Stock exchange 売却リクエストを 外部システムに送信 売却対象の株を ロック

Slide 9

Slide 9 text

マイクロサービスの特徴 9 ● 各サービスは「単一の機能」を提供 ● 各サービスは個別にデータベースを持つ ● サービス間の連携を外部からコントロールする機能(ワークフローマネー ジャー)は存在しない ※ SOA では、ESB がオーケストレーション機能(ビジネスロジック)を実装する   場合が多かった ● 各サービスは、個別にデプロイ・置き換えが可能 ○ サービス手数料の体系が変わった場合は、「Fees service」を丸ごと置き換えること ができる。 「自律的サービス」の意味

Slide 10

Slide 10 text

● 自律性(Autonomy) ○ API を介した疎結合なインターフェース(内部実装、内部データを外部に見せない) ○ 独立に置き換え可能 ● 耐久性(Resilience) ○ 障害の発生領域を最小化(あるサービスが停止しても、他のサービスは停止しない) ○ 他のサービスに影響を与えずに、小さな機能変更を積み重ねていける マイクロサービスが持つべき特性 (1/3) - 開発者視点 10 Order service Implements Uses Public API /v1/addTransaction /v1/getTransactions API を介した 疎結合処理 Stock transaction service

Slide 11

Slide 11 text

マイクロサービスが持つべき特性 (2/3) - SRE 視点 11 ● 観測可能(Observability) ○ アプリケーションログ、トレース、インフラのリソース使用量サービスの状態が外部か ら分からないといけない ● 自動化(Automation) ○ 個々のサービスはシンプルでも、複数のサービスが連携する環境そのものは複雑になり 得る。複数サービスを正しく連携するには、デプロイメントやオペーレションのミスを なくすためにプロセスの自動化が必要

Slide 12

Slide 12 text

マイクロサービスが持つべき特性 (3/3) - SOA との違い 12 ● 整列性(Alignment) ○ 「単一責任の原則」に従ってサービスが 分割され、独立に実装されていること ○ SOA では、技術要件に沿った水平分割が なされて、複数のコンポーネントにまた がる変更が必要になった https://en.wikipedia.org/wiki/Service-oriented_architecture SOA:複数レイヤーの コンポーネントを共有 Micro service database API Logic 垂直スタックを 個別に実装

Slide 13

Slide 13 text

マイクロサービス開発上のチャレンジ (1/2) - 開発者視点 13 ● 適切なサービス分割 ○ 「単一責任の原則」に従ったサービス分割を 実現するには、「将来どのような変更要求が 起こり得るか」を予測する深いドメインナ レッジが必要 ○ 一度実装した機能を他のサービスに移行する のは、労力とリスクを伴う Micro Service A database Micro Service B database データの移行 Micro service アクセス先 /API の移行 マイクロサービス A の機能をマイクロ サービス B に移行する際の影響

Slide 14

Slide 14 text

マイクロサービス開発上のチャレンジ (2/2) - 開発者視点 14 ● API のデザインと変更 ○ サービスの利用側から見て使いやすい API デザインが必要 ○ 機能の追加・変更に伴う API の変更時に、互換性をどのように担保するべきか? ● 分散システムに固有の考慮点 ○ ネットワークを介したサービス連携では、ネットワークの信頼性、帯域、遅延などを考 慮した設計が必要 ● チーム間の連携 ○ サービスごとに個別チームで開発する場合、チームごとの優先順位、開発スケジュール を調整する仕組みが必要

Slide 15

Slide 15 text

マイクロサービス運用上のチャレンジ - SRE 視点 15 ● 分散システムに固有の障害モード ○ モノリシックシステムとは異なるトラブルシューティング・スキルが必要 ● 観測可能性(Observability)の実現 ○ トラブルシューティングに必要な Observability の実現はそれほど容易ではなく、専用 のインフラが必要 Micro service database Market service Stock exchange 外部ネットワーク 障害 内部ネットワーク 障害 依存サービスの 障害停止 依存外部システムの 障害停止 高負荷による 処理遅延 ハードウェア 障害

Slide 16

Slide 16 text

2. マイクロサービスのライフサイクル

Slide 17

Slide 17 text

マイクロサービス開発の流れ(ライフサイクル) 17 ● 本番運用しながら機能を追加していくことが大前提 ○ デザインフェーズは継続的にやってくる ○ 運用 = "Observe" : メトリックからシステムの状態を理解 すること ● 一番最初は、モノリスで実装して、段階的にマイクロサービス化 するという方法もある ○ 初期リリースはモノリスで手早く実装して、ユーザーの反応 を見ながら適切なマイクロサービスのデザインを検討する 設計 開発 デプロイ Observe

Slide 18

Slide 18 text

設計・開発フェーズでの考慮点 - 開発者視点 18 ● 新しい機能をどのように追加するか ○ 既存 API にフィールドを追加 ○ 既存サービスに新しい API を追加 ○ 新しいサービスを追加 ● 他のサービスとの連携方法 ○ 同期処理/非同期処理 ● サービス停止時の影響範囲 Micro service API 既存の API に フィールドを追加 API 既存のサービスに API を追加 Micro service API 新しいマイクロ サービスを追加

Slide 19

Slide 19 text

デプロイフェーズでの考慮点 - 開発者 / SRE 視点 19 ● デプロイ環境の標準化 ○ 今ならコンテナがデフォルト。サービス(アプリケーション)の実行に必要な最小限の バイナリを含んだイメージを利用 ○ 同一のソース/設定からは、必ず同一のイメージをリビルドできる仕組みが必要 ○ Continuous Deployment (継続的デプロイ)パイプラインの構築が必要 コード コミット ビルド 単体テスト ステージング デプロイ 統合テスト プロダクション 環境

Slide 20

Slide 20 text

運用(Observe)フェーズでの考慮点 - SRE 視点 20 ● Observability が必要な理由 ○ 自律的なサービスが相互連携した際に、どのような 動作をするかを完全に予測することはできない ⇨ プロダクション環境における「実際の動作」を  理解することが極めて需要 ● Observability の対象範囲 ○ API リクエストを投入して、レスポンスが得られる までの動作は、ビジネスロジックからインフラまで さまざまなレイヤーが影響 ⇨ すべてのレイヤーの情報を取得することが必要 インフラ OS アプリケーション ビジネスロジック リクエスト レスポンス

Slide 21

Slide 21 text

プロダクション環境におけるロギングインフラ 21 ● 各サービスのログは、共通のロギングサービスに集約して、検索可能にする ● サービスごとにログの粒度やフォーマットが異ならないように、ログ出力の標準化が必要 ● プロダクション環境における複数サービスの連携状態を把握するための基本情報 Order service Order database Fee service Fee rules database ダッシュボード ログサーチ ロギング サービス

Slide 22

Slide 22 text

チーム構成とエンジニアリング文化 22 ● 既存のチーム構成に合わせてマイクロサービスを設計するのではなく、マイクロサービスご とに担当チームを割り当てる ● 各チームは、担当するマイクロサービスの(デプロイ、運用を含めた)フルライフサイクル に責任を持つ ○ サービスの変更は、他のチームの作業に依存せず独立に実施(できるべき) ○ サービス間の連携については、チーム間で共有されたルールを確立する ○ 小さな、独立した変更を継続的に実施することで、変更に伴う問題発生時のリスクを 小さくする ● (テクノロジースタックに依存しない)開発プロセスやデプロイメントプロセス、これらを 支えるツールなどは、すべてのチームに共通の標準化、自動化を行う

Slide 23

Slide 23 text

3. マイクロサービスの設計方針

Slide 24

Slide 24 text

マイクロサービスの採用を検討する際のポイント ● ドメインの複雑性 ○ ビジネスドメインの構造が単純で固定的であれば、モノリシックなシステムでも問題はおきない。 ドメインの構造が複雑で継続的に変化する場合、マイクロサービスの有用性がより高まる ● 技術要件 ○ 技術異質性:サービスごとに異なる技術スタックが採用できる ● 組織の成長 ○ エンジニアリング組織の急速な拡大が見込まれる場合、サービスごとの小さなチーム構成により、 新しく加わるメンバーのオンボーディングをスムーズに保てる ● チームとしての知識の蓄積 ○ マイクロサービスの経験が少ないメンバーで始める際は、まずは、PoC、パイロットなどによるノ ウハウの蓄積が必要 24

Slide 25

Slide 25 text

オンライン投資サービスの実装例 ● 株の売却リクエスト処理をマイクロサービスで実装してみる ● ビジネス視点でどのような機能(Business capability)が必要か? ○ オーダー管理機能 ○ 手数料管理機能 ○ 外部システム連携機能 ○ 所有株の管理機能 ○ ・・・ 25 A 社の株を 100 株売却 売却対象の株を 確保 サービス手数料を 計算・引き落とし 売却リクエストを 外部システムに送信 ユースケースの背後に潜んでいる 「ビジネス機能」を発見することが大切

Slide 26

Slide 26 text

ビジネス要件とアプリーケション機能のマッピング ● サービス分割のポイント:単一責任の原則 ○ 変更する理由が同じものは集める ○ 変更する理由が異なるものは分離する ● 変更理由はビジネス要件から来ることを考える と、「Business capability」ごとにサービスを 割り当てるべき 26 Order service Stock transaction service Fee service Market service 売却リクエストの 情報を記録 サービス手数料 を計算・引き落とし 売却対象の株を ロック 売却リクエストを 外部システムに送信 Business capability ユースケース上の アクション

Slide 27

Slide 27 text

ビジネス要件の分割方法 ● Business capability の分割で悩んだ際は、「変更される理由が異なるものは分割する」と いう原則に従う。 ○ 「Market service」の機能を「Order service」に実装すると「売却リクエストを外部システムに 送信」する機能は、単一のサービスで実装できるが・・・ ● これには、「将来、どのような変更が起こり得るか」までを見通した業務分析が必要 27 Order service Market service 売却リクエストを 外部システムに送信 ○ 外部システムを追加するごとに、Order service に変更が必要になる ○ 複数プロトコルの外部システムに対応し ていくと、「売却リクエスト管理業務」 と無関係な技術的複雑さが増していく

Slide 28

Slide 28 text

サービス間の連携方法の検討 28 ● 基本は、外部公開された API を介した 同期処理。それでは、非同期処理が好 ましいケースは・・・? サービス手数料を 計算・引き落とし Order service A 社の株を 100 株売却 Stock transaction service 売却リクエストの 情報を記録 Order database Transaction database Fee service Fee rules database Market service Stock exchange 売却リクエストを 外部システムに送信 売却対象の株を ロック

Slide 29

Slide 29 text

同期処理に伴う問題点 29 ● 「Order service」が本質的に「ワークフローマネージャー」になっており、他のサービス は、Order service に依存した「自律性の低い」サービスになっている。 ● 「株の売却リクエスト」に伴うワークフローに新しい処理(例えば、「売却リクエストの 内容を別途メールで通知する」など)を追加するごとに、Order service に変更が必要にな り、Order service のロジックが複雑化する恐れがある。 ● エンドユーザーは、ワークフローが完了するまで待たされる。さらに、外部システムの障 害(Stock exchange が売却リクエストを受け付けないなど)があると、ワークフローがエ ラーになり、エンドユーザーにエラーが返る → エンドユーザー的には、リクエストは正常に受け付けて、裏でリトライして欲しい

Slide 30

Slide 30 text

非同期処理を用いた「Service choreograph」 30 ● Order service は「売却リクエストを受 け付けた」というイベントを発行して処 理を終了。他のサービスは(Pub/Sub 方 式で)イベントを受け取り、自分が担当 する処理を自発的に実行する サービス手数料を 計算・引き落とし Order service A 社の株を 100 株売却 Stock transaction service 売却リクエストの 情報を記録 Order database Transaction database Fee service Fee rules database Market service Stock exchange 売却リクエストを 外部システムに送信 売却対象の株を ロック メッセージキュー メッセージキュー 売却リクエスト 登録 売却リクエスト 送信完了

Slide 31

Slide 31 text

非同期処理を用いた「Service choreograph」 31 ● この方式の場合、新しい処理を追加するのに、Order service を変更する必要はない ● サービスの自律性が高まる事で、耐障害性も高まる。例えば、Market service が停止し て、売却リクエストの受付は可能 ※ キュー上のメッセージをロストしなければ、Market service が復帰した時点で処理が再開する

Slide 32

Slide 32 text

サービスの外部公開 32 ● 外部クライアントに対しては、必要な機能のみを API ゲートウェイを介して公開する ○ クライアント認証、アクセスロギングなどを行う ● 複数のサービスを呼び出して、結果をまとめて返す「API composition」を実装することも できるが、API ゲートウェイにビジネスロジックを実装するのは好ましくない Order service Fee service Market service API ゲートウェイ Submit Order Strategy service Create Strategy クライアント

Slide 33

Slide 33 text

Stock transaction service Market service Order service プロダクション環境へのデプロイメント 33 ● 各サービスは、ロードバランサーを用いて個別に スケールアウトさせる ● 当然ながら、サービス単位のスケーラビリティを 意識した設計が必要 ● サービスディスカバリーの仕組みも必要 Order database Transaction database メッセージキュー メッセージキュー ロード バランサー ロード バランサー

Slide 34

Slide 34 text

4. マイクロサービスのアーキテクチャー

Slide 35

Slide 35 text

モノリスとマイクロサービスの比較 ● 単一のマイクロサービスは、MVC モデルの Web アプリケーションと対比できる。 35 クライアント プレゼンテーション ビジネスロジック データモデル データベース 上位サービス API ビジネスロジック データモデル データベース Order service Order database 下位サービス サービスが管理する エンティティのデータ のみを保持する 他のサービスと連携し て機能を提供する

Slide 36

Slide 36 text

マイクロサービスの 4tier モデル ● マイクロサービスを取り囲むシステム全体としては、次の 4つのレイヤーについて考える必要がある ○ クライアント : マイクロサービスを利用する外部コン ポーネント ○ バウンダリー : クライアントに公開するインター フェース(API ゲートウェイ) ○ サービス : サービスとして実装する機能 ○ プラットフォーム : サービスをデプロイするインフラ 36 クライアント バウンダリー サービス プラットフォーム サポート 機能の公開 機能の利用

Slide 37

Slide 37 text

マイクロサービスプラットフォームの役割 ● マイクロサービスプラットフォームは、すべてのサービスが共通に必要とする次の機能を 標準化して提供する 37 ○ ネットワーク接続、コンピュー ティングリソース ○ デプロイメントパイプライン ○ サービス間の通信機能(同期・ 非同期メッセージングサービ ス) ○ ロギング、モニタリング Micro service A Micro service B 同期/非同期 通信 ロギング ロギング 実行環境(ランタイム) デプロイメントパイプライン

Slide 38

Slide 38 text

サービスの依存関係 ● この例では、Orders service は 他のサービスを利用する「上位 サービス」の位置にあることが わかる 38 サービス手数料を 計算・引き落とし Order service A 社の株を 100 株売却 Stock transaction service 売却リクエストの 情報を記録 Order database Transaction database Fee service Fee rules database Market service Stock exchange 売却リクエストを 外部システムに送信 売却対象の株を ロック

Slide 39

Slide 39 text

サービスの依存関係 ● サービス間の依存関係を分析することで、各サービスの Criticality(そのサービスが停止 した時の影響範囲)が判断できる 39 Order service Fee service Market service Submit Order Strategy service Create Strategy REST API gRPC Micro service Micro service 複数のサービスが 依存している 下位サービスは すべての上位サービス に影響する

Slide 40

Slide 40 text

Order service Stock transaction service Fee service Market service Command Command Command リクエスト サービスの依存パターン ● サービスの依存パターンの典型例として、Aggregator と Coordinator がある。 ● 新機能を追加する際は、「既存サービスを拡張する」「Aggregator を追加する」     「Coordinator を追加する」などの選択肢を比較検討することになる 40 Order service Market service Query リクエスト Query Fee service 売却リクエスト 売却状況確認 Aggregator パターン ⇨ 複数サービスのデータを集約 Coordinator パターン ⇨ 複数サービスの機能を連携

Slide 41

Slide 41 text

サービス間の連携方式:同期処理 ● 呼び出し先のサービスの処理結果がわからないと次に進めない場合に用いる ● REST API、gRPC などで実装 ● サービス間が密結合して、サービスの自律性が損なわれやすい ● 特に複数の同期呼び出しがチェーン状につながると、レスポンス待ち時間の増加や、1つの サービスが停止した際の影響範囲が大きくなるなどのデメリットが生じる 41 Order service Market service Stock exchange リクエスト レスポンス リクエスト レスポンス

Slide 42

Slide 42 text

サービス間の連携方式:非同期処理 ● サービスは「イベント」をメッセージングキューに発行する ● 他のサービスは、イベントを受け取って処理する ● イベントを発行するサービスは、このイベントをどのサービスが受け取るかは考えない ● イベントを受け取るサービスは、このイベントをどのサービスが発行したかは考えない 42 Order service Market service Stock exchange イベント イベント イベント ・・・ イベント発行 イベント取得 Fee service

Slide 43

Slide 43 text

非同期処理における負荷分散の方式 43 Topic Subscriber A Subscriber B Service A-1 Service A-2 Service Service B-1 Publish Register 負荷分散 Pub/Sub 側で事前に定義 Subscriber C Pull サブスクリプション Push サブスクリプション Service C ロード バランサー Push 配信 ● Pub/Sub の場合は、Pull サブスクリプションと Push サブスクリプションで負荷分散の方法が異なる

Slide 44

Slide 44 text

アプリケーションバウンダリー 44 ● サービスを外部公開する際は、 クライアントの特性に応じた API 変換のゲートウェイが必要 ● アプリケーション内部において も、業務ドメイン(サブシステ ム)ごとにバウンダリーを設け て、特定の API のみを他のドメ インに公開する場合がある 管理 UI パブリック API Web UI iOS app Android app マイクロサービス アプリケーション Order service Fee service Market service Strategy service 内部ゲートウェイ オーダー管理 サブシステム

Slide 45

Slide 45 text

API ゲートウェイ 45 ● セキュリティバウンダリーとし て、Reverse Proxy の役割を果 たす ● API ゲートウェイ内部で、認 証、サービスルーティング、送 受信データの変換などを行うこ ともできる Order service Fee service Market service クライアント Order service クライアント 認証 ルーティング データ変換 API ゲートウェイ

Slide 46

Slide 46 text

BFF (Backend for Frontend) パターン 46 ● API ゲートウェイの開発(変更)はクライアントの開発(変更)と連携が必要 ● 単一の API ゲートウェイで対応すると「単一責任の原則」が破られて、クライアントの開 発に合わせた API ゲートウェイの変更が困難になる ● クライアントごとに API ゲートウェイを分けて、クライアントの開発チームが対応する ゲートウェイの開発も合わせて担当する パブリック API Web UI iOS app Android app マイクロサービス アプリケーション iOS ゲートウェイ Android ゲートウェイ Web ゲートウェイ API ゲートウェイ

Slide 47

Slide 47 text

フロントエンド設計の注意点 47 ● フロントエンドで複数のバッ クエンド機能を集約・連携す る場合、「フロントエンドモ ノリス」が生まれないように 注意が必要 ● フロントエンド側も独立した コンポーネントが連携する、 マイクロサービス的な実装が 求められる 「単一責任の原則」に 従ったサービス分割 全ての機能が1つのフロント エンドアプリケーションに集約 モジュール A モジュール B モジュール C

Slide 48

Slide 48 text

Thank You.