Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~(Spring Fest 2020講演資料)

モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~
(Spring Fest 2020講演資料)

2020年12月17日

NTTデータ
技術革新統括本部
横井 一輝

  • Soyez le premier à commenter

モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~(Spring Fest 2020講演資料)

  1. 1. © 2020 NTT DATA Corporation モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~ 2020年12月17日 NTTデータ 技術革新統括本部 横井一輝
  2. 2. © 2020 NTT DATA Corporation 2 アジェンダ モノリスからマイクロサービスへの移行(説明編) • マイクロサービスとは • ストラングラーパターンで段階的な移行 • 段階的に移行するための方針 モノリスからマイクロサービスへの移行(実装編) • サービスの切り出し • ロードバランサーによる負荷分散 • サーキットブレーカーによる障害対応 マイクロサービスへの移行戦略として、ストラングラーパターンがあります Spring Cloud を用いた実現例を交えながら、ストラングラーパターンについて紹介します
  3. 3. © 2020 NTT DATA Corporation 3 自己紹介 名前: 横井一輝 所属: NTTデータ 技術革新統括本部 業務: アプリケーションのモダナイゼーション支援 趣味: ドライブ、サウナ、温泉 自己紹介 • 保守性の高いソフトウェアを構築することに興味・関心 • 現在、Spring Framework を勉強中 興味・関心 発表者近影
  4. 4. © 2020 NTT DATA Corporation 4 モノリスからマイクロサービスへの移行 ~説明編~
  5. 5. © 2020 NTT DATA Corporation 5 モノリス と マイクロサービス モノリス DB DB API-Gateway DB DB マイクロサー ビス マイクロサー ビス マイクロサー ビス マイクロサー ビス 単一の大きなシステムが 全ての業務を実行 複数の小さなサービスが 連携して業務を実行
  6. 6. © 2020 NTT DATA Corporation 6 モノリス と マイクロサービス のメリット・デメリット モノリスとマイクロサービスにはそれぞれメリット・デメリットがあり、トレードオフの関係となる モノリスの特徴 敏捷性 スケーリング 技術仕様・要件充足 パフォーマンス データ 回復性 運用・監視 アプリケーション全体でデプロイ 全体をスケールしなければならない 個別最適不可だが技術スタックがシンプル パフォーマンスが劣化しにくい データの一貫性を保障しやすい システム全体に影響する 管理の手間が少ない 組織面の一致 アーキテクチャと組織の不一致による負荷 再利用 機能を再利用する機会は従来通り 赤文字:メリット マイクロサービスの特徴 サービスごとにデプロイ、迅速な仕様変更 サービスごとにスケーリングが可能 個別最適化可能だが技術スタック複雑化 パフォーマンスが劣化しやすい データの一貫性が保障しにくい サービスが隔壁となり一部の影響に留まる 管理対象が増える アーキテクチャを組織に一致させて高効率 機能を再利用する機会を広げる
  7. 7. © 2020 NTT DATA Corporation 7 モノリス から マイクロサービス への移行 モノリス DB DB API-Gateway DB DB マイクロサー ビス マイクロサー ビス マイクロサー ビス マイクロサー ビス マイクロサービスに移行する際はデメリットが顕在化しやすいため、対応が必要 技術仕様の 複雑化 性能問題 データ 整合性 運用 複雑化
  8. 8. © 2020 NTT DATA Corporation 8 モノリスからマイクロサービスへの移行の際に考えること なぜ移行するのか 移行目的の明確化 代替手段の検討 成功基準の明確化 どこで分割するか コードの分割断面 データベースの分割断面 どのサービスから分割する か ビジネス価値軸 分割容易性軸 モノリスと マイクロサービスの統合 データ連携 データ整合性 【今回の発表内容】 移行方針 一度に分割か?段階的に分割か? リスクを抑えた移行方針とは?
  9. 9. © 2020 NTT DATA Corporation 9 マイクロサービス移行方針
  10. 10. © 2020 NTT DATA Corporation 10 一度に分割するか、段階的に分割するか 一度に分割する ビッグバンリライト 段階的に分割する ストラングラーパターン VS
  11. 11. © 2020 NTT DATA Corporation 11 ビッグバンリライト モノリスを捨て去り、マイクロサービスへ一度に分割する方法 モダナイゼーション全般において、ビッグバンリライトはリスキーで失敗に終わる可能性が高い DB API-Gateway DB DB メッ セージ ユー ザー UI 3つの機能を サービスとして分割 DB 単一の大きなシステム 3つの機能が存在 ユーザー メッセージ UI
  12. 12. © 2020 NTT DATA Corporation 12 ストラングラーパターン 徐々にモノリスを小さくし、マイクロサービスへ段階的に分割していく方法 クライアントからのアクセスをストラングラーファサードがインターセプトし、モノリスまたは新サービスにルーティング クライアントのアクセス先はストラングラーファサードから変わらないので、マイクロサービス移行を意識しなくてよい 新 サ ー ビ ス 新 サ ー ビ ス 新 サ ー ビ ス 新 サ ー ビ ス ストラングラーファサー ド モノリス 新 サ ー ビ ス 新 サ ー ビ ス ストラングラーファサー ド モノリス 新 サ ー ビ ス ストラングラーファサー ド 早期切り出し あとで切り出し 切り出し完了 アクセスを インターセプト アクセス先は 変わらない アクセスを 振り分ける
  13. 13. © 2020 NTT DATA Corporation 13 【参考】チャットアプリでのストラングラーパターン利用例 ストラングラーファサードとしてAPI Gateway を利用し、メッセージ機能から段階的にサービスとして分割していく API-Gateway DB メッ セージ メッセージ機能以外を モノリスに残して サービスとしてコピー DB ユー ザー UI Step2 Step3 DB API-Gateway DB DB メッ セージ ユー ザー UI 3つの機能を サービスとして分割 DB 単一の大きなシステム 3つの機能が存在 ユーザー メッ セージ UI Step1 API-Gateway
  14. 14. © 2020 NTT DATA Corporation 14 ビッグバンリライト vs ストラングラーパターン ビッグバンリライト ストラングラーパターン メリット • 移行全体の実装コストは少ない • 失敗のリスクを抑えられる • 移行完了まで待たずに段階的に移行の効果 を得られる • 移行と共に組織を成熟させられる デメリット • 失敗のリスクが高い • リライトが完了するまで、効果が得られない • ストラングラーファサードの実装コストがかかる ユースケース • 小規模なシステム • 移行失敗のリスクが少ない • 移行完了までの期間が短い • 開発組織がマイクロサービスに成熟 • 大規模なシステム • 移行失敗のリスクを抑えたい • 移行完了までの期間が長い • 開発組織がマイクロサービスに未成熟
  15. 15. © 2020 NTT DATA Corporation 15 ストラングラーパターンを利用して、段階的に移行する3つの方法 新機能をサービスとして実装 プレゼンテーション層とバックエンドの分離 モノリスを分解してマイクロサービスに抽出
  16. 16. © 2020 NTT DATA Corporation 16 方法① 新機能をサービスとして実装 メリット:新規サービスを迅速に実装できる デメリット:既存システムを変更することが難しい DB API-Gateway 単一の大きなシステム 3つの機能が存在 新規サービスを実装 ユーザー メッセージ UI DB ユーザー メッセージ UI DB 新規 サー ビス
  17. 17. © 2020 NTT DATA Corporation 17 方法② プレゼンテーション層とバックエンドの分離 メリット:プレゼンテーション層とバックエンドが独立して開発ができる デメリット:バックエンドに、大きなモノリスが残り続ける DB 単一の大きなシステム 3つの機能が存在 ユーザー メッセージ UI DB UI機能を、ユーザー・ メッセージ機能から分 離 ユーザー メッセージ UI
  18. 18. © 2020 NTT DATA Corporation 18 方法③ モノリスを分解してマイクロサービスに抽出 メリット:既存システムのアーキテクチャを大幅に改善し、マイクロサービスのメリットをより多く享受できる デメリット:他のパターンと比較して難易度が高い API-Gateway DB メッ セージ モノリスの メッセージ機能を抽出 DB ユー ザー UI DB 単一の大きなシステム 3つの機能が存在 ユーザー メッセージ UI メッ セージ
  19. 19. © 2020 NTT DATA Corporation 19 ストラングラーパターンを利用して、段階的に移行する方法の比較 新機能のサービス実装 プレゼンテーション層と バックエンドの分離 モノリスを分解して マイクロサービスに抽出 メリット • 新規サービスを 迅速に実装できる • プレゼンテーション層とバックエン ドが独立して開発ができる • アーキテクチャを大幅に改善し、 マイクロサービスのメリットを より多く享受できる デメリット • 既存システムを変更することが 難しい • バックエンドに、大きなモノリスが 残り続ける • 他のパターンより難易度が高い ユースケース • モノリスの分解は行わない • マイクロサービスの早い段階で の実証 • UI/UXの独立した開発・テスト • 将来プレゼンテーション層から マイクロサービスAPIを呼び出し • モノリスのアーキテクチャを改善 • モノリスに実装されている機能 をマイクロサービスとして抽出
  20. 20. © 2020 NTT DATA Corporation 20 モノリスからマイクロサービスへの移行 ~実装編~
  21. 21. © 2020 NTT DATA Corporation 21 マイクロサービス移行 シナリオ とある会社で、モノリシックなチャットアプリをモダナイズするというシナリオの中で、 マイクロサービス移行に関連する設計手法や技術を説明していきます。 あと、マイクロサービス 流行ってるらしいから 検討してみて(^^) ユーザー数増えてきたから メッセージ送受信の キャパを向上させて欲しい マイクロサービス? ナニそれ? オイシイの?
  22. 22. © 2020 NTT DATA Corporation 22 チャットアプリの現行アーキテクチャ 開発言語:Java フレームワーク:Spring Boot データベース:HSQL 実装機能: 1. UI 2. ユーザー管理機能 3. メッセージ管理機能 DB ユーザー メッセージ UI Spring Boot メッセージ管理機能の スケーラビリティ向上が マイクロサービス移行の目的 こちらのチャットアプリをサンプルアプリとして、マイクロサービス移行の検証を行なっていきます
  23. 23. © 2020 NTT DATA Corporation 23 新機能のサービス実装 プレゼンテーション層と バックエンドの分離 モノリスを分解して マイクロサービスに抽出 メリット • 新規サービスを 迅速に実装できる • プレゼンテーション層とバックエン ドが独立して開発ができる • アーキテクチャを大幅に改善し、 マイクロサービスのメリットを より多く享受できる デメリット • 既存システムを変更することが 難しい • バックエンドに、大きなモノリスが 残り続ける • 他のパターンより難易度が高い ユースケース • モノリスの分解は行わない • マイクロサービスの早い段階で の実証 • UI/UXの独立した開発・テスト • 将来プレゼンテーション層から マイクロサービスAPIを呼び出し • モノリスのアーキテクチャを改善 • モノリスに実装されている機能 をマイクロサービスとして抽出 今回採用したストラングラーパターン メッセージ管理機能 を改善したいので選択
  24. 24. © 2020 NTT DATA Corporation 24 マイクロサービス 移行手順 最初に、ストラングラーパターンでマイクロサービスの切り出しを行う その後、ロードバランサーやサーキットブレーカーを実装し、よりクラウドネイティブにシフトしていく DB ユー ザー メッ セージ UI API-Gateway DB メッ セージ DB ユー ザー UI API-Gateway DB メッ セージ DB ユー ザー UI メッ セージ API-Gateway DB メッ セージ DB ユー ザー UI メッ セージ ストラングラーパターン によるサービス切り出し ロードバランサによる 負荷分散 サーキットブレーカによる 障害対応 メッ セージ メッ セージ
  25. 25. © 2020 NTT DATA Corporation 25 ストラングラーパターンによるサービス切り出し
  26. 26. © 2020 NTT DATA Corporation 26 ストラングラーパターンによるサービス切り出し DB API-Gateway DB メッ セージ ユーザー メッ セージ UI DB ユー ザー UI ストラングラーパターンを使って、メッセージサービスを安全に切り出し Spring Cloud Gatewayを利用してAPI ゲートウェイを実装 ストラングラーパターン でメッセージサービス に切り出し メッセージ機能を 安全に切り出して スケーラビリティ 向上させたい
  27. 27. © 2020 NTT DATA Corporation 27 Spring Cloud Gateway とは • 様々な要素でルーティングルールを設定 • URLパス • ヘッダーやクッキーの値 • メソッド(GET、POSTなど) • 時間(〇時以前、以降など) • リクエスト、レスポンスの内容をフィルターで書き換え • サーキットブレーカー、サービスディスカバリ、セキュリティの機能との統合も可能 • 類似のライブラリ Spring Cloud Netflix Zuul はメンテナンスモードに移行 現在は Spring Cloud Gateway の使用が推奨されてる API ゲートウェイ を構築するための、シンプルかつ柔軟な ライブラリ 今回の検証バージョン Spring Boot 2.3.5, Spring Cloud Hoxton.SR8
  28. 28. © 2020 NTT DATA Corporation 28 Step 1. ストラングラーファサードの実装 1. ストラングラーファサードの実装 2. モノリスからマイクロサービスへの 抽出(AP) 3. モノリスからマイクロサービスへの 抽出(DB) 4. ストラングラーファサードの呼び出し 先の書き換え 5. 認証情報の連携 API-Gateway DB ユーザー メッセージ UI localhost:8080 localhost:8081 Spring Cloud Gateway Spring Boot
  29. 29. © 2020 NTT DATA Corporation 29 ストラングラーファサードの実装 1. Spring Initializr から Spring Cloud Gateway を依存関係に追加したアプリケーションを作成 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> Mavenを利用する場合 pom.xml に追記 Gateway を追加
  30. 30. © 2020 NTT DATA Corporation 30 ストラングラーファサードの実装 2. RouteLocator の Bean を作成し、ルーティングルールを設定 @SpringBootApplication public class Application { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(p -> p.path("/**") .uri("http://localhost:8081") ) .build(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } } パスのパターンマッチにアスタリスクで全マッチ 全リクエストをモノリス(localhost:8081)に転送 Java config の場合 (yaml で記述することも可能)
  31. 31. © 2020 NTT DATA Corporation 31 Step 1. ストラングラーファサードの実装 の課題 ■課題 Logout実行時、リダイレクト先を示す Locationヘッダーが :8081/login で帰ってくるため 正しくページ遷移しない ■アプローチ API Gatewayにて、 Location ヘッダーの値を書き換える 必要がある API-Gateway DB ユーザー メッセージ UI localhost:8080 localhost:8081 :8081/Logout :8080/Logout Location :8081/Login Location :8081/Login × Location :8080/Login ○
  32. 32. © 2020 NTT DATA Corporation 32 レスポンスの Location ヘッダーの値を書き換え(実装) return builder.routes() .route(p - > p .path("/**") .filters(f - > f .rewriteLocationResponseHeader("AS_IN_REQUEST", "Location", "localhost:8080", "http")) .uri("http://localhost:8081") ) .build(); レスポンスヘッダーに Location が存在する場合は フィルターでホスト名を localhost:8080 に書き換え
  33. 33. © 2020 NTT DATA Corporation 33 Step 2. モノリスからマイクロサービスへの抽出(AP) 1. ストラングラーファサードの実装 2. モノリスからマイクロサービスへの 抽出(AP) 3. モノリスからマイクロサービスへの 抽出(DB) 4. ストラングラーファサードの呼び出し 先の書き換え 5. 認証情報の連携 localhost:8080 localhost:8081 API-Gateway メッ セージ DB ユー ザー UI メッ セージ localhost:8082 Spring Boot
  34. 34. © 2020 NTT DATA Corporation 34 Step 2. モノリスからマイクロサービスへの抽出(AP)の課題 ■課題 共通ライブラリの存在や 他機能と密結合しているなどで、 メッセージサービスだけをきれいに 抽出することが困難 ■解決策 メッセージサービスだけを 抽出しようとせずに、 大きめにサービスを抽出してから、 不要なコードを削ぎ落としていく localhost:8080 localhost:8081 DB ユー ザー UI メッ セージ localhost:8082 Spring Boot ユー ザー UI ユー ザー UI メッ セージ API-Gateway
  35. 35. © 2020 NTT DATA Corporation 35 Step 3. モノリスからマイクロサービスへの抽出(DB) 1. ストラングラーファサードの実装 2. モノリスからマイクロサービスへの 抽出(AP) 3. モノリスからマイクロサービスへの 抽出(DB) 4. ストラングラーファサードの呼び出し 先の書き換え 5. 認証情報の連携 localhost:8080 localhost:8081 API-Gateway メッ セージ DB ユー ザー UI メッ セージ Spring Boot localhost:8082 ユー ザー メッ セージ メッ セージ メッ セージ
  36. 36. © 2020 NTT DATA Corporation 36 Step 3. モノリスからマイクロサービスへの抽出(DB) の課題 ■課題 以下の場合、モノリスとマイクロサービス のデータ連携を設計する必要がある • 切り出すAPとモノリスに残るAPが 同一のテーブルにアクセス • 切り出すテーブルとモノリスに残る テーブルが、外部結合している (今回のパターン) ■解決策の選択肢 • モノリスAPを通して モノリスDBのデータを参照 • モノリスDBに マイクロサービスAPが直接参照 • モノリスDB更新をトリガーに マイクロサービスDBに更新を反映 DB ユー ザー UI メッ セージ API-Gateway DB メッ セージ Spring Boot ユーザー情報 更新リクエスト ユーザー テーブル更新 ユー ザー メッ セージ 最新のユーザー情報 はどこ?
  37. 37. © 2020 NTT DATA Corporation 37 モノリスからマイクロサービスへのデータ連携の解決策 API-Gateway メッ セージ ユー ザー UI API-Gateway メッ セージ ユー ザー UI API-Gateway メッ セージ ユー ザー UI ユー ザー ユー ザー ユー ザー メッ セージ メッ セージ メッ セージ ユー ザー モノリスAPを通して モノリスDBのデータを参照 モノリスDBに マイクロサービスAPが直接参照 モノリスDB更新をトリガーに マイクロサービスDBに更新を反映 メリット: サービスの疎結合が保たれる デメリット: モノリスAPの修正が必要 メリット: 実装コストが低い デメリット: モノリスDBと密結合になる メリット: サービスの疎結合が保たれる デメリット: 更新反映用の部品が必要 参照 更新
  38. 38. © 2020 NTT DATA Corporation 38 Step 4. ストラングラーファサードの呼び出し先の書き換え 1. ストラングラーファサードの実装 2. モノリスからマイクロサービスへの 抽出(AP) 3. モノリスからマイクロサービスへの 抽出(DB) 4. ストラングラーファサードの呼び出 し先の書き換え 5. 認証情報の連携 localhost:8080 localhost:8081 API-Gateway DB ユー ザー UI メッ セージ localhost:8082 UI・ユーザー機能 メッセージサービス DB メッ セージ
  39. 39. © 2020 NTT DATA Corporation 39 Step 4. ストラングラーファサードの呼び出し先の書き換え の課題 ■課題の背景 STOMP というメッセージングプロトコル (WebSocket通信の一種) を利用して、チャットの送受信を実装 ■課題 WebSocket通信とHTTP通信の 通信プロトコルの違いによる ルーティング設定ができない ■解決法 STOMPプロトコルに沿った URLパスベースのルーティングを 設定する必要がある STOMPのメッセージフロー
  40. 40. © 2020 NTT DATA Corporation 40 STOMP プロトコルに沿った 切り出し先サービスへのルーティング設定(実装) return builder.routes() .route(p - > p .path("/chat/messages").or().path("/messages/**") .uri("http://localhost:8082")) .route(p - > p .path("/topic/**").or().path("/chat/messages/{segment}/**") .uri("ws://localhost:8082")) .route(p - > p .path("/**") .filters(f - > f .rewriteLocationResponseHeader("AS_IN_REQUEST", "Location", "localhost:8080", "http")) .uri("http://localhost:8081")) .build(); WebSocket 通信用の ルーティング設定 http通信用の ルーティング設定
  41. 41. © 2020 NTT DATA Corporation 41 Step.5 認証情報の連携 1. ストラングラーファサードの実装 2. モノリスからマイクロサービスへの 抽出(AP) 3. モノリスからマイクロサービスへの 抽出(DB) 4. ストラングラーファサードの呼び出し 先の書き換え 5. 認証情報の連携 API-Gateway DB ユー ザー UI メッ セージ DB メッ セージ 太郎さんが ログイン 太郎さんが メッセージ送信 太郎さんを 認証 メッセージ送信 したのは誰?
  42. 42. © 2020 NTT DATA Corporation 42 Step.5 認証情報の連携の課題 ■課題 モノリシックなシステムでは セッション認証を採用していた。 しかし、切り出し先のマイクロサービスは モノリシックが認証した情報を 知ることができない。 ■解決策の選択肢 • 単純なBasic 認証 • JWTを使ったトークン認証 ← 採用 • OAuth 2.0 認証・認可 API-Gateway DB ユー ザー UI メッ セージ DB メッ セージ セッション認証 認証情報をどう 連携するのか?
  43. 43. © 2020 NTT DATA Corporation 43 JWTを 返却 Step.5 認証情報の連携(アクセストークン認証) 1. ユーザーIDとパスワードを入力して ログインリクエストを送る 2. モノリスにログインリクエストを ルーティングする 3. モノリスが JWT トークンを クッキーに入れて返却 4. メッセージサービスを呼び出すとき JWT トークンをクッキーに含む リクエストを送る 5. APIゲートウェイが JWT トークンを Authorizationヘッダーに 組み込む 6. メッセージサービスが JWT トークンを検証 API-Gateway DB ユー ザー UI メッ セージ DB メッ セージ ① ② ④ ⑤ ⑥ IDとPWで ログイン IDとPWで ログイン JWTをクッキー に与える JWTを認可ヘッダー に与える JWTを 検証 ③
  44. 44. © 2020 NTT DATA Corporation 44 認証情報の連携(実装) return builder.routes() .route(p - > p .path("/chat/messages").or().path("/messages/**") .filters(f - > f .filter(preGatewayFilterFactory.apply(new Config())) .uri("http://localhost:8082")) .route(p - > p .path("/topic/**").or().path("/chat/messages/{segment}/**") .filters(f - > f .filter(filter(preGatewayFilterFactory.apply(new Config())) .uri("ws://localhost:8082")) .route(p - > p .path("/**") .filters(f - > f .rewriteLocationResponseHeader("AS_IN_REQUEST", "Location", "localhost:8080", "http")) .uri("http://localhost:8081")) .build(); ゲートウェイ フィルタ を自作し リクエストやレスポンスの中身を 自由自在に書き換え可能
  45. 45. © 2020 NTT DATA Corporation 45 認証情報の連携(実装) public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> { (中略) @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { Optional<HttpCookie> token = Optional.ofNullable(exchange.getRequest().getCookies().getFirst("USERINFO")); if (token.isEmpty()) return chain.filter(exchange); ServerHttpRequest.Builder builder = exchange.getRequest().mutate(); builder.headers((httpHeaders) -> { httpHeaders.set("Authorization", token.get().getValue()); }); return chain.filter(exchange.mutate().request(builder.build()).build()); }; } (中略) } Authorization ヘッダーに アクセストークンを付与 Cookie 情報から アクセストークンを取得 自作した ゲートウェイ フィルタ
  46. 46. © 2020 NTT DATA Corporation 46 マイクロサービス移行 シナリオ ~途中経過~ マイクロサービス移行の第一段階を終え、メッセージ管理機能の切り離しに成功。 当初の「メッセージ管理機能の性能向上」の目的を果たすため、引き続きマイクロサービス移行を実施する。 ところで、 メッセージ機能の性能は 向上したのかね?? マイクロサービス移行。 ご苦労だった。 できたー! マイクロサービス 完全に理解!! 性能向上の目的 を忘れてた……
  47. 47. © 2020 NTT DATA Corporation 47 ロードバランサーによる負荷分散
  48. 48. © 2020 NTT DATA Corporation 48 ロードバランサーによる負荷分散 API-Gateway DB メッ セージ DB ユー ザー UI API-Gateway DB メッ セージ DB ユー ザー UI メッ セージ メッ セージ ロードバランサーを使って、アクセスの負荷を分散 Spring Cloud LoadBalancer と Spring Cloud Netflix Eureka を利用 メッセージサービスを 多重化して ロードバランサーで 負荷分散 アクセス集中時の メッセージサービスへの 負荷を分散したい
  49. 49. © 2020 NTT DATA Corporation 49 Spring Cloud LoadBalancer と Spring Cloud Netflix Eureka とは Spring Cloud LoadBalancer • ロードバランサーを構築するためのライブラリ • メンテナンスモードに移行した Netflix Ribbon の代わりに使用が推奨 • Ribbon で行っていた作業を抽象化して提供されている Spring Cloud Netflix Eureka • Netflix 社製のサービスディスカバリ用のサービスレジストリとクライアントを構築するライブラリ • サービスディスカバリを利用することで、DNSのようにサービス名からIPアドレス取得することが可能 • Eureka はメンテナンスモードへの移行はいまのところ宣言されていない ロードバランサーとサービスディスカバリを Spring で構築するためのライブラリ 今回の検証バージョン Spring Boot 2.3.5, Spring Cloud Hoxton.SR8
  50. 50. © 2020 NTT DATA Corporation 50 Step 1. Eureka サービスレジストリ の作成・起動 1. Eureka サービスレジストリを 作成・起動 2. クライアントを サービスレジストリに登録 3. サービス一覧を取得し、 リクエストをロードバランサーで分散 API-Gateway DB ユー ザー UI メッ セージ DB メッ セージ サービス レジストリ メッ セージ サービス名 アドレス ①起動
  51. 51. © 2020 NTT DATA Corporation 51 Eureka サービスレジストリ の作成・起動(実装) 1. Spring Initializr から Eureka Server を依存関係に追加した アプリケーションを作成 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> Mavenを利用する場合 Eureka サービスレジストリの 依存関係をpom.xml に追記 Eureka Server を追加
  52. 52. © 2020 NTT DATA Corporation 52 Eureka サービスレジストリ の作成・起動(実装) 2. テスト用の設定を application.properties に追記 3. サービスレジストリを有効にするためアノテーション “@EnableEurekaServer” を追加 @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } Eureka サービスレジストリの アプリケーションクラスに @EnableEurekaServer を追加 server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false logging.level.com.netflix.eureka=OFF logging.level.com.netflix.discovery=OFF テスト用の単純目的のため 自分自身の登録を無効化
  53. 53. © 2020 NTT DATA Corporation 53 Step 2. サービスレジストリに登録 1. Eureka サービスレジストリを 作成・起動 2. クライアントを サービスレジストリに登録 3. サービス一覧を取得し、 リクエストをロードバランサーで分散 API-Gateway DB ユー ザー UI メッ セージ DB メッ セージ サービス レジストリ メッ セージ ②登録 ①起動 サービス名 アドレス サービス名 アドレス message localhost:8082 localhost:8083
  54. 54. © 2020 NTT DATA Corporation 54 サービスレジストリに登録(実装) 1. メッセージサービスに Eureka Discovery Client の依存関係を追加 2. サービスレジストリに登録するためのアノテーション “@EnableDiscoveryClient” を追加 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> @EnableDiscoveryClient @SpringBootApplication public class MessageApplication { public static void main(String[] args) { SpringApplication.run(MessageApplication.class, args); } } メッセージサービスの pom.xml に依存関係を追記 メッセージサービスの アプリケーションクラスに @EnableDiscoveryClient を追加
  55. 55. © 2020 NTT DATA Corporation 55 サービスレジストリに登録(実装) 3. サービスレジストリに登録するサービス名を application.properties に設定 4. 同じサービス名で複数起動することで、多重度が上がる server.port=8082 spring.application.name=message サービス名を設定 server.port=8082 spring.application.name=message server.port=8083 spring.application.name=message メッセージサービス① 用のプロパティ メッセージサービス② 用のプロパティ
  56. 56. © 2020 NTT DATA Corporation 56 Step 3.サービス一覧を取得し、リクエストをロードバランサで分散 1. Eureka サービスレジストリを 作成・起動 2. クライアントを サービスレジストリに登録 3. サービス一覧を取得し、 リクエストをロードバランサで分散 API-Gateway DB ユー ザー UI メッ セージ DB メッ セージ サービス レジストリ メッ セージ ②登録 ①起動 ③リクエスト分散 ③サービス一覧を取得 サービス名 アドレス message localhost:8082 localhost:8083
  57. 57. © 2020 NTT DATA Corporation 57 サービス一覧を取得し、リクエストをロードバランサで分散(実装) 1. Spring Cloud Gateway に Eureka Discovery Client の依存関係を追加 2. Spring Cloud Gateway の application.properties に設定 spring.cloud.gateway.discovery.locator.enabled=true spring.cloud.loadbalancer.ribbon.enabled=false <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> Spring Cloud Gatewayの pom.xml に 依存関係を追記 サービスディスカバリを有効化して サービス一覧を取得する設定 Netflix Ribbon を無効化し Spring Cloud LoadBalancer を 有効化するための設定
  58. 58. © 2020 NTT DATA Corporation 58 API ゲートウェイからのアクセスをロードバランサで振り分け(実装) 3. Spring Cloud Gateway の RouteLocator の Bean を修正しロードバランシングできるように設定 return builder.routes() .route(p - > p .path("/chat/messages").or().path("/messages/**") .uri("lb://message")) .route(p - > p .path("/topic/**").or().path("/chat/messages/{segment}/**") .uri("lb:ws://message")) `lb://[サービス名]` と記述することで ロードバランサを利用可能 http://localhost:8082 → lb://message WebSocket通信の際は `lb:ws://[サービス名]` と記述する ws://localhost:8082 → lb:ws://message
  59. 59. © 2020 NTT DATA Corporation 59 サーキットブレーカーによる障害対応
  60. 60. © 2020 NTT DATA Corporation 60 サーキットブレーカーによる障害対応 API-Gateway DB メッ セージ DB ユー ザー UI メッ セージ メッ セージ API-Gateway DB メッ セージ DB ユー ザー UI メッ セージ メッ セージ サーキットブレーカーを使って、サーバー高負荷時はアクセスを一時遮断 Spring Cloud Circuit Breaker と Resilience4J を利用 サーバーレスポンスが 遅い場合は アクセスを一時遮断 サーバー高負荷時に サーバーレスポンスが 遅い場合も アクセスは止まらない
  61. 61. © 2020 NTT DATA Corporation 61 Spring Cloud Circuit breaker とは • メンテナンスモードに移行した Netflix Hystrix の代わりに使用が推奨 • さまざまなサーキットブレーカーの実装にわたって抽象化を提供されており、 開発者はアプリケーションのニーズに最適なサーキットブレーカーを選択可能 • 下記のサーキットブレーカーと組み合わせて使用可能 • Hystrix • Resilience4J • リアクティブ Resilience4J ← 今回使用 • Spring Retry • Sentinal サーキットブレーカーを Spring で構築するためのライブラリ 今回の検証バージョン Spring Boot 2.3.5, Spring Cloud Hoxton.SR8
  62. 62. © 2020 NTT DATA Corporation 62 サーキットブレーカによる障害対応(実装) 1. Spring Cloud Gateway に Resilience4j の依存関係を追加 2. Spring Cloud Gate に Resilience4j の設定を修正する Bean を追記 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId> </dependency> Spring Cloud Gatewayの pom.xml に追記 @Bean public Customizer <ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() { return factory - > factory .configureDefault(id - > new Resilience4JConfigBuilder(id) .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults()) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofSeconds(4)).build()) .build()); } 4秒以内にレスポンスがない場合 サーキットブレーカーが発動する設定
  63. 63. © 2020 NTT DATA Corporation 63 サーキットブレーカによる障害対応(実装) 3. Spring Cloud Gateway の RouteLocator にサーキットブレーカーフィルターを追加 4. Spring Cloud Gateway に アクセス遮断時の既定レスポンスを実装 .route(p -> p.path(“/chat/messages”).or().path(“/messages/**”) .filters(f -> f .circuitBreaker(c -> c.setFallbackUri("forward:/fallback"))) .uri("lb://message")) @RequestMapping("/fallback") public Mono<String> fallback () { return Mono.just("You can't access message service..."); } アクセス遮断時に呼ばれる URIを設定 アクセス遮断時の 既定レスポンス
  64. 64. © 2020 NTT DATA Corporation 64 まとめ
  65. 65. © 2020 NTT DATA Corporation 65 マイクロサービス移行 シナリオ ~エピローグ ~ マイクロサービス移行を終え、メッセージ管理機能の切り離しと、負荷分散・障害対応を実施。 マイクロサービス・リーダーに任命され、引き続きマイクロサービス移行を担当していくことに。 君を マイクロサービス・リーダー に任命する。 今度こそ マイクロサービス移行。 ご苦労だった。 やったー! マイクロサービス リーダーだ!!
  66. 66. © 2020 NTT DATA Corporation 66 まとめ モノリスを分割することで、ミドルウェアが隠ぺいしていたことの再設計が必要になる 段階的に移行する方針は、設計漏れを早期に発見できる点で、リスクを下げて移行できる 今後は分割断面の見つけ方や、モノリスとマイクロサービス間のデータ連携について検証していきたい また、今回は Spring Cloud を用いてロードバランサやサーキットブレーカを実装した しかしこれらは、Istio などのサービスメッシュや AWS などのクラウドサービスでも同様のことができる 今後、これらとの比較検証も行っていきたい 気づき • リスクをさげてマイクロサービスに移行する戦略として、ストラングラーパターンの紹介 • マイクロサービスに移行するためのデモンストレーション • ストラングラーパターンの実装 • ロードバランサの実装 • サーキットブレーカを実装 まとめ
  67. 67. © 2020 NTT DATA Corporation 67 参考情報 Spring I/O 2018 報告会 - Spring Cloud Gateway / Spring Cloud Pipelines https://www.slideshare.net/JunyaKatada/spring-io-2018-spring-cloud-gateway-spring- cloud-pipelines ぱぱっと理解するSpring Cloudの基本 https://www.slideshare.net/kazukikumagai1/spring-cloud Introducing Spring Cloud Gateway by Spencer Gibb @ Spring I/O 2018 https://www.youtube.com/watch?v=NkgooKSeF8w Monolith to Microservice デモアプリ https://github.com/spencergibb/monolith-to-microservices
  68. 68. © 2020 NTT DATA Corporation 本資料に記載されている会社名、商品名、又はサービス名は、各社の登録商標又は商標です。

×