ウェルスナビのマルチサービス化を支える技術 〜Spring Cloud GatewayとPub/Subの実践〜

2.3K Views

May 30, 26

スライド概要

JJUG CCC 2026 Spring ランチスポンサーセッション登壇資料

サービス基盤グループ ソフトウェアエンジニアリングチーム 斎藤 優介・星原 宏紀

ウェルスナビ(WealthNavi)は"働く世代に豊かさを"というミッションのもと、長期運用を前提とした全自動資産運用サービスを提供しています。
マルチサービス化を進める上で、サービス間の認可制御・データ連携方法の標準化が課題となってきました。
本セッションでは、安定したサービス間通信を実現するための二つの取り組みについて解説します。
前半は、Spring Cloud Gatewayを用いたAPI Gatewayの構築についてです。
Java 25やSpring Boot 4といった最新スタックを見据え、Virtual Threadsを採用した背景や、Resilience4jを用いたレジリエンス設計の勘所を共有します。
後半は、Amazon SNS/SQSとSpring Cloud AWSを活用したイベント駆動アーキテクチャの実装についてです。導入に至った背景や設計時の注意点に加え、各キューの特性・デッドレターキューの扱い・テスト方針など、実際の運用に関する実践的な知見をコードを交えて紹介します。
最新のJavaエコシステムを活用するために試行錯誤した実践知をお話しします。

profile-image

ウェルスナビ株式会社 技術広報チームの公式アカウントです。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

ウェルスナビのマルチサービス化を支える技術 〜Spring Cloud GatewayとPub/Subの実践〜 2026.5.30 JJUG CCC 2026 Spring サービス基盤グループ ソフトウェアエンジニアリングチーム 斎藤 優介‧星原 宏紀

2.

資料リンク 下記QRコードを読み込んでいただくと、資料をお⼿元でご覧いただけます。 © WealthNavi Inc. All Rights Reserved. 2

3.

⾃⼰紹介 斎藤 優介 (Yusuke Saito) ウェルスナビ株式会社 サービス基盤グループ ソフトウェアエンジニアリング (SWE) チーム ウェルスナビでは Java / Spring Bootを⽤いたバックエンド開発を主軸に、全社横断の技 術的負債の解消や開発標準化に従事。 ひとこと 本⽇はよろしくお願いいたします。 3 @2025 WealthNavi Inc.

4.

⾃⼰紹介 星原 宏紀 (Koki Hoshihara) ウェルスナビ株式会社 サービス基盤グループ ソフトウェアエンジニアリング (SWE) チーム ウェルスナビでは 共通ライブラリ開発(⼤規模バッチ / 認証系)、バックエンド開発、 新規システムのパフォーマンスチューニング、新技術導⼊ を推進 ひとこと 初のスポンサーセッションで緊張してます。 本⽇はよろしくお願いいたします! 4 @2025 WealthNavi Inc.

5.

アジェンダ はじめに Spring Cloud Gateway を活⽤した API Gateway Spring Cloud AWS を活⽤したイベント駆動アーキテクチャ まとめ 5

6.

プロダクト紹介 全⾃動の資産運⽤サービス ウェルスナビ 「⻑期‧積⽴‧分散」でリターンの最⼤化をめざす 1万円から運⽤できる 全⾃動でおまかせできる リスクを抑えて運⽤できる NISAも⾃動で活⽤できる ※画面はイメージです © WealthNavi Inc. All Rights Reserved. 6

7.

出典: https://kabu.com/company/pressrelease/20260324_1.html © WealthNavi Inc. All Rights Reserved. 7

8.

1 はじめに © WealthNavi Inc. All Rights Reserved. 8

9.

はじめに 本セッションのターゲットは、以下のいずれかに当てはまる⽅を想定します ● ● Java25、Spring Boot4の新機能を利⽤した開発に興味がある Java、Spring Bootを使ったAPI Gatewayや、データ連携の開発に興味がある © WealthNavi Inc. All Rights Reserved. 9

10.

背景‧⽬的 マルチサービス化 資産運⽤(証券)から保険、その他⾦融商品、資産構成変更のアドバイスまで事業領域を拡⼤す るなか、中核となるMAP(総合アドバイザリープラットフォーム)の構築を進めている。 加えて、「エムット」におけるAIネイティブな資産形成体験をシームレスに提供するために、多 ⾓化するサービス群を⽀えるための「サービス間連携の標準化」が不可⽋。 サービス間データ連携における課題 API同期連携における横断的関⼼事の個別実装による属⼈化。また、可⽤性と疎結合性を両⽴す る⾮同期連携活⽤のための、技術標準が未確⽴。 © WealthNavi Inc. All Rights Reserved. 10

11.

マルチサービス化 ⼀つのウェルスナビID(共通ID)を⼊⼝に複数サービスをシームレスに接続し、資産運⽤を含む 様々な⾦融サービスを個別最適された形で提供できる個⼈向け⾦融プラットフォームの実現。 サービス連携 API 資産運⽤ ID基盤 顧客 MAP ウェルスナビID ⾃社事業 エコシステム 提携 サービス 保険 デジタル バンク © WealthNavi Inc. All Rights Reserved. 11

12.

従来のデータ連携のアーキテクチャ全体像 個別実装による属⼈化された APIによる同期データ連携 NativeApp Public API API WebApp Internet ServerSide xxClient PrivateProxy ThirdParty/ SaaS API Internet API xxSDK Private xxService API ServerSide External xxClient API クライアント層 サービス層 同期データ連携が適切でない © WealthNavi Inc. All Rights Reserved. 12

13.

API Gatewayとイベント駆動の導⼊ API Gateway導⼊ NativeApp Public API API WebApp Internet ServerSide xxClient PrivateProxy ThirdParty/ SaaS API Internet API xxSDK Private xxService ServerSide External xxClient API クライアント層 © WealthNavi Inc. All Rights Reserved. API サービス層 イベント駆動型 データ連携導⼊ 13

14.

2 1 Spring Cloud Gateway を活⽤した API Gateway © WealthNavi Inc. All Rights Reserved. 14

15.

Spring Cloud Gateway を活⽤した API Gateway 1. API Gateway を導⼊した同期データ連携 2. Spring Cloud Gateway の採⽤背景 3. Spring Cloud Gateway によるルーティング制御および認証プロキシの構築 4. Resilience4j によるレジリエンス実装 5. Spring Security を活⽤した共通認可 © WealthNavi Inc. All Rights Reserved. 15

16.

API Gateway 不在 ● ● API連携部分の実装が個別に独⽴しており、認証‧認可やログ出⼒、通信などの横断的関 ⼼事が適切に管理できていない状態である。 クライアント層、サービス(API) 層の運⽤保守が標準化されておらず、属⼈化傾向にあ る。 NativeApp Public API WebApp Internet ServerSide xxClient PrivateProxy ThirdParty/ SaaS API Internet API xxSDK Private © WealthNavi Inc. All Rights Reserved. xxService API クライアント層 サービス層 横断的関⼼事が個別管理、標準化されていない 全体を把握するのが困難 16

17.

API Gatewayを導⼊した同期データ連携 ● ● ● API連携の実装における認証‧認可(権限管理)、通信制御などの横断的関⼼事はゲート ウェイが解決する役割を担う。 単⼀障害点のリスクに対応しつつ、集約によるメリットを選択する。 マルチサービス間のデータ連携ハブとして機能させる。 NativeApp Public ID基盤 API SSO(※) WebApp Internet ServerSide PrivateProxy 標準化 クライアント API API セッション SSO 新規事業 App 標準化 クライアント 事業横断でのID連携 ‧SSOを実現 クライアント層 ThirdParty/ SaaS APIゲートウェイ ‧ルーティング ‧認証‧認可 ‧通信制御 ‧トレーシング Private API サービス層 集約 集約 (※)トークン交換仕様(RFC8693)を利⽤した有効なセッションを取得する実装 © WealthNavi Inc. All Rights Reserved. 17

18.

API Gatewayが解決する横断的関⼼事と対応する技術要素 Spring Framework / Spring Boot Spring Cloud Gateway ルーティング Resilience4j (Spring Cloud 統合) Spring Security レジリエンス (通信制御) 認可 (OAuth 2.0) 認証プロキシ © WealthNavi Inc. All Rights Reserved. 18

19.

Spring Cloud Gateway を活⽤した API Gateway 1. API Gateway を導⼊した同期データ連携 2. Spring Cloud Gateway の採⽤背景 3. Spring Cloud Gateway によるルーティング制御および認証プロキシの構築 4. Resilience4j によるレジリエンス実装 5. Spring Security を活⽤した共通認可 © WealthNavi Inc. All Rights Reserved. 19

20.

API Gateway 構築における技術選定 データ連携におけるハブとなるAPIゲートウェイというプロダクトの性質上、複 数のチームによって継続的に参照‧改修されることが想定される。 開発‧運⽤体制の⼀貫性と効率性を最優先 ウェルスナビバックエンドにおいて習熟度の⾼い技術‧サービスを採⽤ © WealthNavi Inc. All Rights Reserved. 20

21.

Spring Cloud Gateway 採⽤理由  1. 既存資産の活⽤ Spring Framework は社内の標準的な技術スタックであり、既存のJava資産を最⼤限 に活⽤可能。社内の開発標準‧監視設定にも容易に準拠できる  2. 独⾃のロジック注⼊ SaaSでは困難な複雑な条件分岐や、ビジネス要件に基づいた独⾃ロジックを柔軟に 注⼊することが可能  3. リリースの⾃律性 インフラチームのスケジュールに依存することなく、アプリケーションチーム独⾃の リリースサイクルで運⽤が可能 © WealthNavi Inc. All Rights Reserved. 21

22.

Spring Cloud Gateway とは Spring 上に API ゲートウェイを構築するためのライブラリ。API へのルーティングをシンプル かつ効果的に⾏う⽅法を提供し、セキュリティ、監視 / メトリクス、回復⼒といった横断的な問 題に対応可能。 歴史 WebFlux版 の誕⽣ Netflix 社の Zuul 1.x に代わる形で Spring チームによって開発。 ⾮同期‧ノンブロッキングな WebFlux ベースとして登場。 Java 21 / Virtual Threads 2023年に Virtual Threads が追加。 ⾮同期コードを記述せずとも、⾼性能を維持することが可能になった。 MVC版 のリリース(GA) Spring Boot 3.2(Java 17 以上対応)。 Virtual Threads と併⽤することで、馴染みのある MVC モデルで⾼スループットを実現可能に。 出典: https://spring.pleiades.io/projects/spring-cloud-gateway © WealthNavi Inc. All Rights Reserved. 22

23.

MVC vs WebFlux ● ● MVC 版を採⽤ Virtual Threads 利⽤を前提とした場合、パフォーマンスが同等であれば、デバッグしやす く資産も活かせる MVC が合理的 項⽬ MVC WebFlux 記述スタイル 命令型 宣⾔型 / リアクティブ 直感的なコード Flux/Mono によるストリーム操作 パフォーマンス WebFlux 相当 ⾼いスループット Virtual Threads を活⽤可能 限られたリソースで効率的に動作 デバッグ‧保守 容易 困難 スレッドを追えるため直感的 トレースが複雑化しやすい 学習コスト 低い ⾼い 従来の Java 開発知識を転⽤できる リアクティブ特有の思考が必要 既存資産の活⽤ 制限なし 制限あり 既存の同期ライブラリが安全 ⾮同期ライブラリの使⽤が推奨 © WealthNavi Inc. All Rights Reserved. 23

24.

Virtual Threads Virtual Threads は、OSではなくJavaランタイムによって実装されるJavaスレッドです。 従来のスレッド(プラットフォーム‧スレッド)との違いは、⾮常に多くの(何百万も)アク ティブな Virtual Threads を同じJavaプロセスで簡単に実⾏できる点です。 リクエストごとのスレッド‧スタイルで記述されたサーバー‧アプリケーションをより効率的 に実⾏できるため、スループットの向上とハードウェアの浪費の軽減につながります。  ⾼スループットを実現  API Gateway との親和性◎ I/O待ち(ネットワークやDB接続など) が多い⼤量のタスク処理に最適 ⼤量のHTTPクライアント‧コール(I/O操 作)を伴うタスクを処理する、APIゲート ウェイの要件に⾮常にマッチ。 Virtual Threads は⾼速スレッドではない 速度(低レイテンシ)ではなく、スケール(⾼ス ループット)を提供する技術 出典: https://docs.oracle.com/javase/jp/21/core/virtual-threads.html#GUID-8AEDDBE6-F783-4D77-8786-AC5A79F517C0 © WealthNavi Inc. All Rights Reserved. 24

25.

Spring Boot での Virtual Threads 有効⽅法 ● ● ● アプリケーションプロパティから設定可能(Java 24 以上推奨、Spring Boot 3.2 以降)。 Spring Framework 内部で利⽤される、Tomcat / Jetty 等のサーブレットスレッド(リクエ スト処理スレッド)や各種 Task Executor が Virtual Threads に切り替わる。 ⼀⽅で、サードパーティライブラリ側については、個別に対応が必要。(詳細は後述) ○ 従来のスレッドプール(プラットフォームスレッドプール)を利⽤している場合があ るため。 spring.threads.virtual.enabled=true © WealthNavi Inc. All Rights Reserved. 25

26.

利⽤バージョン Java 25 Spring Framework / Spring Boot v4.0.5 Spring Cloud Gateway Resilience4j (Spring Cloud 統合) Spring Security v5.0.1 v2.3.0 v7.0.4 © WealthNavi Inc. All Rights Reserved. 26

27.

Spring Cloud Gateway を活⽤した API Gateway 1. API Gateway を導⼊した同期データ連携 2. Spring Cloud Gateway の採⽤背景 3. Spring Cloud Gateway によるルーティング制御および認証プロキシの構築 4. Resilience4j によるレジリエンス実装 5. Spring Security を活⽤した共通認可 © WealthNavi Inc. All Rights Reserved. 27

28.

Spring Cloud Gateway によるルーティング制御 Spring Framework / Spring Boot Spring Cloud Gateway ルーティング Resilience4j (Spring Cloud 統合) Spring Security レジリエンス (通信制御) 認可 (OAuth 2.0) 認証プロキシ © WealthNavi Inc. All Rights Reserved. 28

29.

パスベースルーティング ● ● パスベースのルーティングを採⽤し、API Gateway のI/Fとしてはパスにバックエンド サービスの「事業ドメイン」と「サービス名」をプレフィックスとして付与する プレフィックスを元にバックエンドサービスを解決し、プレフィックスを除去したパス へプロキシする GET /domainX/serviceA/** Spring Cloud Gateway Host: serviceA.wealthnavi.com GET /** Domain X API A クライアント ルーティング処理 API B © WealthNavi Inc. All Rights Reserved. 29

30.

Spring Cloud Gateway の機能概要 ● Spring Cloud Gateway (MVC版) は、ルート、述語、フィルターの3要素を組み合わせて ⾼度なルーティングを実現。 ルート / Route 述語 / Predicates フィルター / Filter © WealthNavi Inc. All Rights Reserved. ルーティングの基本単位 ● ● ID、述語、フィルターの集合で定義される 述語が⼀致(true)した場合、そのルートが選択される HTTPリクエストの属性(ヘッダー、パス、クエリ等)と条件を照合する機能。 ● ● Spring WebMvc.fn 準拠 / RequestPredicate を使⽤ すべてのリクエスト情報にアクセス可能 リクエストやレスポンスの加⼯を⾏う機能。HandlerFilterFunction が実体。 ● ● 送信「前」または「後」に処理を挿⼊ 柔軟なカスタム実装をサポート 30

31.

フィルターの種類 ⼀般的に利⽤される機能は標準フィルターとして提供されている。加えてカスタム実装 も可能 ● 標準フィルター Spring Cloud Gateway (WebMVC) で提供される標準機能 ● ヘッダー操作: リクエスト/レスポンスヘッダーの追加‧削除 ● パス操作: 転送時のパス書き換え、プレフィックス除去 ● 通信制御: リトライ制御 カスタムフィルター HandlerFilterFunction インターフェースを実装することで作成可能 例:認証プロキシ - バックエンドのリクエスト時に認証を⾏うフィルターなど © WealthNavi Inc. All Rights Reserved. 31

32.
[beta]
ルーティング制御実装サンプル
Java Configuration によるルーティング定義構成例

●

implementation 'org.springframework.cloud:spring-cloud-starter-gateway-server-webmvc'

@Configuration
public class GatewayConfig {
@Bean
public RouterFunction<ServerResponse> gatewayRouter() {
return GatewayRouterFunctions.route("x_a_service") // ルート定義
.route(GatewayRequestPredicates.path("/domainX/serviceA/**"), // 述語適用
HandlerFunctions.http())
.before(BeforeFilterFunctions.uri("https://A.wealthnavi.com")) // フィルター適用①
.before(BeforeFilterFunctions.stripPrefix(2)) // フィルター適用②
.build();
}
}

© WealthNavi Inc. All Rights Reserved.

32

33.

ルーティング制御構成イメージ ● Spring MVC 標準のフィルターに Spring Cloud Gateway の各機能が適⽤されて処理され る GET /domainX/serviceA/** Spring Cloud Gateway Host: serviceA.wealthnavi.com GET /** Route Domain X ルーティング処理 API A クライアント Predicates API B Filter © WealthNavi Inc. All Rights Reserved. 33

34.

Spring Cloud Gateway による認証プロキシ処理 Spring Framework / Spring Boot Spring Cloud Gateway ルーティング Resilience4j (Spring Cloud 統合) Spring Security レジリエンス (通信制御) 認可 (OAuth 2.0) 認証プロキシ © WealthNavi Inc. All Rights Reserved. 34

35.

認証のオフロード(Authentication Offloading) ● トークン交換(RFC 8693 OAuth 2.0 トークン交換)またはトークン取得を代⾏した上 で、Bearer ヘッダーに付与してバックエンドへ送る GET /domainX/serviceA/** Spring Cloud Gateway Route GET /token 外部 認可サーバ ルーティング処理 Domain X クライアント 認証 認証処理 API A Host: serviceA.wealthnavi.com Authorization: Bearer XXX GET /** © WealthNavi Inc. All Rights Reserved. 35

36.
[beta]
認証プロキシの実装サンプル①
カスタムフィルター実装例
HandlerFilterFunctionインターフェースを実装したフィルター関数を定義

●
●

@Component
public class AuthorizationOffloadingHandlerFilterFunctions {
public HandlerFilterFunction<ServerResponse, ServerResponse> instrument() {
return (request, next) -> {
String accessToken = authNService.getToken(); // 1. 任意の認証方式でアクセストークン取得処理
ServerRequest modified = ServerRequest.from(request)
.headers(headers ->
// 2. 取得したアクセストークンを HTTPヘッダーに付与
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken))
.build();
return next.handle(modified);
};
}
}

© WealthNavi Inc. All Rights Reserved.

36

37.
[beta]
認証プロキシの実装サンプル②
作成したフィルターをルート定義に追加

●

@Configuration
public class GatewayConfig {
+

@Autowired

+

private AuthorizationOffloadingHandlerFilterFunctions customFilter;
@Bean
public RouterFunction<ServerResponse> gatewayRouter() {
return GatewayRouterFunctions.route("x_a_service")
.route(GatewayRequestPredicates.path("/domainX/serviceA/**"),
HandlerFunctions.http())
.before(BeforeFilterFunctions.uri("https://A.wealthnavi.com"))
.before(BeforeFilterFunctions.stripPrefix(2))

+

.before(AuthorizationOffloadingHandlerFilterFunctions.instrument()) // カスタムフィルター適用
.build();
}

}

© WealthNavi Inc. All Rights Reserved.

37

38.

認証プロキシ構成イメージ ● ルーティング処理と合わせてカスタムフィルターによる認証処理が実⾏される GET /domainX/serviceA/** Spring Cloud Gateway Route GET /token 外部 認可サーバ ルーティング処理 クライアント Domain X 認証処理 認証 カスタムFilter API A Host: serviceA.wealthnavi.com Authorization: Bearer XXX GET /** © WealthNavi Inc. All Rights Reserved. 38

39.

Spring Cloud Gateway を活⽤した API Gateway 1. API Gateway を導⼊した同期データ連携 2. Spring Cloud Gateway の採⽤背景 3. Spring Cloud Gateway によるルーティング制御および認証プロキシの構築 4. Resilience4j によるレジリエンス実装 5. Spring Security を活⽤した共通認可 © WealthNavi Inc. All Rights Reserved. 39

40.

Resilience4j による通信制御とレジリエンス向上 Spring Framework / Spring Boot Spring Cloud Gateway ルーティング Resilience4j (Spring Cloud 統合) Spring Security レジリエンス (通信制御) 認可 (OAuth 2.0) 認証プロキシ © WealthNavi Inc. All Rights Reserved. 40

41.

レジリエンスの重要性 レジリエンス (Resilience)とは? 障害が発⽣することを前提に、そこから「いかに素早く回復し、被害を最⼩限に抑えるか」 という回復⼒を指す。 API Gateway におけるレジリエンスの重要性 API Gateway は「単⼀障害点」となるため、レジリエンスを担保することは極めて重要 ここでの障害はシステム全体へ波及するため、耐障害性の確保が必要 © WealthNavi Inc. All Rights Reserved. 41

42.

Resilience4j とは ● ● 分散システムにおける通信制御を通じてレジリエンスを向上させるための、フォールト レランス(耐障害性)ライブラリ。 外部サービスとの通信において、様々なトラフィック制御パターンを Java アプリケー ションへ容易に実装できる。 提供機能 resilience4j-circuitbreaker: 失敗率や遅延を監視し、通信を遮断‧試⾏する。 resilience4j-retry: リトライ。指数バックオフなどを⽤いて再試⾏を制御する。 resilience4j-bulkhead: リソースを分離‧制限し、局所的な障害の波及を防ぐ。 resilience4j-timelimiter: 処理時間を監視し、上限を超えた場合に中断させる。 resilience4j-ratelimiter: リクエスト数を制限し、過負荷から保護する。 © WealthNavi Inc. All Rights Reserved. 42

43.

Spring Cloud 統合 ● ● Spring Cloud Gateway で通信制御⽤のフィルターを提供しているが限定的。 Resilience4j を Spring Cloud エコシステムへ統合するためのライブラリを利⽤すること で⾼度な通信制御が利⽤可能。 レジリエンス機能 Spring Cloud 統合 標準フィルター サーキットブレーカー フル機能利⽤可能 なし(※) ⾼度な設定(指数バックオフ等) Retry フィルター 柔軟な制御ロジック RateLimiter フィルター 標準対応 なし(限定的) リトライ レートリミッター バルクヘッド / タイムリミット (※)標準で「CircuitBreaker フィルター」が用意されているが、これは Spring Cloud 統合を前提としたフィルター © WealthNavi Inc. All Rights Reserved. 43

44.

サーキットブレーカー処理イメージ ● ● 通信結果を監視して、失敗率を管理 失敗率がしきい値を超えた場合、通信を遮断して即座にエラーを返す Spring Cloud Gateway Route ルーティング処理 Domain X 認証処理 障害 (1) リクエスト (2) タイムアウト クライアント (3) リクエスト API A (4) エラー 通信制御処理 © WealthNavi Inc. All Rights Reserved. 44

45.

サーキットブレーカー実装サンプル① ● ● ● Spring Cloud 統合ライブラリを依存関係に追加 アプリケーションプロパティから Resilience4j 設定を構成 通信先ごとに設定を個別に管理可能 implementation rg.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j' resilience4j.circuitbreaker: configs: default: failureRateThreshold: 30 # 失敗率の閾値 slidingWindowType: COUNT_BASED # リクエスト数で判定 slidingWindowSize: 50 # 判定に使う直近のリクエスト数 instances: x_a_service_cb: # 通信先ごとの定義(今回は上記で定義したデフォルト設定を適用) base-config: "default" © WealthNavi Inc. All Rights Reserved. 45

46.
[beta]
サーキットブレーカー実装サンプル②
●

Spring Cloud Gateway が提供する CircuitBreaker フィルターを利⽤することで、①で構
成した設定が適⽤される
@Configuration
public class GatewayConfig {
@Bean
public RouterFunction<ServerResponse> gatewayRouter() {
return GatewayRouterFunctions.route("x_a_service")
.route(GatewayRequestPredicates.path("/domainX/serviceA/**"), HandlerFunctions.http())
.before(BeforeFilterFunctions.uri("https://A.wealthnavi.com"))
.before(BeforeFilterFunctions.stripPrefix(2))
.before(AuthorizationOffloadingHandlerFilterFunctions.instrument())
+

.filter(CircuitBreakerFilterFunctions.circuitBreaker(config -> config

+

.setId("x_a_service_cb") // ①で定義した ID

+

.setStatusCodes("500", "502", "503", "504")))
.build();
}

}

© WealthNavi Inc. All Rights Reserved.

46

47.

通信制御構成イメージ ● Resilience4j の Spring Cloud 統合で通信制御を構成 Spring Cloud Gateway Route ルーティング処理 Domain X 認証処理 障害 (1) リクエスト (2) タイムアウト クライアント (3) リクエスト API A 通信制御処理 (4) エラー Resilience4j Filter © WealthNavi Inc. All Rights Reserved. 47

48.

Virtual Threads 利⽤時の注意点 resilience4j-bulkhead ● デフォルト(FixedThreadPoolBulkhead)はプラットフォームスレッドを使⽤する ● 対策: SemaphoreBulkhead を使⽤するか、Bulkhead ⾃体を無効化する resilience4j-circuitbreaker ● デフォルトの実⾏スレッドが Executors.newCachedThreadPool() になっている ● 対策: Executors.newVirtualThreadPerTaskExecutor() を明⽰的に使⽤するよう設定変更する Rerilience4j 側でも Virtual Threads 対応は進められている(※) プロパティ(resilience4j.thread.type=virtual)による切り替え (※) https://github.com/resilience4j/resilience4j/pull/2335 を参照 © WealthNavi Inc. All Rights Reserved. 48

49.

Spring Cloud Gateway を活⽤した API Gateway 1. API Gateway を導⼊した同期データ連携 2. Spring Cloud Gateway の採⽤背景 3. Spring Cloud Gateway によるルーティング制御および認証プロキシの構築 4. Resilience4j によるレジリエンス実装 5. Spring Security を活⽤した共通認可 © WealthNavi Inc. All Rights Reserved. 49

50.

Spring Security を活⽤した共通認可 Spring Framework / Spring Boot Spring Cloud Gateway ルーティング Resilience4j (Spring Cloud 統合) Spring Security レジリエンス (通信制御) 認可 (OAuth 2.0) 認証プロキシ © WealthNavi Inc. All Rights Reserved. 50

51.

認可のオフロード(Authorization Offloading) ● ● サービスごとに認可処理を独⾃実装せず、API Gateway が認可を担う ID基盤と連携して、RFC 9068 に準拠した認可処理(アクセストークン検証、スコープに よるアクセス制御)を実施 API Gateway Domain X Spring Cloud Gateway / Resilience4j JWTトークン 認可済み クライアント Spring Security API API 共通認可処理 API 1. トークン検証 2. スコープ検証 認証要求 公開鍵の取得 ID基盤 © WealthNavi Inc. All Rights Reserved. 51

52.
[beta]
RFC 9068準拠のデコーダー実装サンプル
●
●

Spring Security 6.5で追加されたRFC 9068対応APIを利⽤し、NimbusJwtDecoderを⽣成
SecurityFilterChainに登録することで、仕様に厳格に準拠したアクセストークン検証を容
易に実現
public JwtDecoder rfc9068JwtDecoder() {
// 1. デコーダーの生成(JWKS URLの設定)
NimbusJwtDecoder decoder = NimbusJwtDecoder
.withJwkSetUri("https://id.wealthnavi.com/.well-known/jwks.json")
.validateType(false) // typ検証は後続のValidatorに委譲するため無効化
.build();
// 2. RFC 9068準拠のバリデータ構成(typ, iss, exp, aud, client_id を一括検証)
OAuth2TokenValidator<Jwt> rfc9068Validator = JwtValidators.createAtJwtValidator()
.issuer("https://id.wealthnavi.com")

// issクレーム

.audience("https://apigw.wealthnavi.com")

// audクレーム

.clientId("my-client-id")

// client_idクレーム

.build();
decoder.setJwtValidator(rfc9068Validator);
return decoder;
}

© WealthNavi Inc. All Rights Reserved.

52

53.
[beta]
パスベースのアクセス制御を含めた認可実装サンプル
●

●

API Gateway はエンドポイントの実装(Controller)を持たないため、アノテーション
(@PreAuthorize)ではなく SecurityFilterChain によるパスベースの集中型アクセス制
御を実施する
RFC 9068準拠のデコーダーを登録する
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(auth -> auth
// GETリクエストは参照権限(read)を要求
.requestMatchers(HttpMethod.GET, "/domainX/apiA/**").access(hasScope("read:domainX:apiA"))
// それ以外の更新系リクエスト(POST/PUT等)は更新権限(write)を一括要求
.requestMatchers("/domainX/apiA/**").access(hasScope("write:domainX:apiA"))
// 定義外のパスはすべて認証済みであることを要求
.anyRequest().authenticated()
)
// RFC 9068準拠のデコーダーを適用
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(rfc9068JwtDecoder())))
.build();
}

© WealthNavi Inc. All Rights Reserved.

53

54.
[beta]
Tips: JWKS URL へのリトライ実装サンプル
●
●

NimbusJwtDecoder はデフォルトで JWKS 取得時のリトライ機構を持たないため、瞬断
がサービス全体の障害に繋がるリスクがある
公開鍵取得に使⽤する RestTemplate に Spring Retry を適⽤することで、レジリエンス
を向上させる(JwkSetUriJwtDecoderBuilder#restOperations に設定)
public RestTemplate jwkSetRequestRestTemplate() {
// リトライポリシーの設定( SocketTimeoutExceptionを対象)
var policy = RetryPolicy.builder().maxRetries(maxRetries).includes(SocketTimeoutException.class).build();
var retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(policy);
// インターセプターでリトライ処理を注入
var restTemplate = new RestTemplate();
restTemplate.setInterceptors(List.of((req, body, exec) -> {
try {
return retryTemplate.execute(ctx -> exec.execute(req, body));
} catch (RetryException e) {
throw new IOException("JWKS fetch failed after retries", e);
}
}));
return restTemplate;
}

© WealthNavi Inc. All Rights Reserved.

54

55.

Enjoy Spring Cloud Gateway! © WealthNavi Inc. All Rights Reserved. 55

56.

3 1 Spring Cloud AWS を活⽤した イベント駆動アーキテクチャ © WealthNavi Inc. All Rights Reserved. 56

57.

Spring Cloud AWS を活⽤したイベント駆動アーキテクチャ 1. イベント駆動アーキテクチャ採⽤の動機付け 2. Pub/Subの概念とAWSでの構成 3. Spring Cloud AWSによる実装詳細 4. 運⽤‧設計上の考慮事項 © WealthNavi Inc. All Rights Reserved. 57

58.

API 連携とイベント駆動型データ連携の整理 ● ● API 連携(同期):呼び出し結果をその場で確認できる。 イベント駆動型(⾮同期):1対多で配信できるため、スケールアウトしやすい(※)。 API 連携 イベント駆動型データ連携 Request - Response Pub/Sub 連携 連携先 A ① Request 呼び出し元 呼び出し先 ② Response ① Publish Message Publisher Broker ② Subscribe 連携先 B © WealthNavi Inc. All Rights Reserved. (※)補足:以降「Pub/Sub 連携」と記載。 58

59.

イベント駆動型への移⾏によるメリット 更新処理をイベントに分離することで、呼び出し元の責務を減らし、連携先の追加や⼀時 的なエラーに対するリトライを扱いやすくする。 ● API連携で更新処理を担う場合の課題 課題①:呼び出し元の複雑化 ● 連携先の状態に応じた複雑な制御が必要 ● リトライロジックが肥⼤化 課題②:連携先サービス障害時の復旧負荷が⾼い ● 障害時は該当時間帯の処理が⼀律失敗する ため、呼び出し元が再実⾏を管理する必要 がある © WealthNavi Inc. All Rights Reserved. イベント駆動型を採⽤した場合の対応 解決策①-1:更新処理の簡素化 ● ⾮同期化でトランザクション制御を簡素化 解決策①-2:主体性の明確化 ● 更新の責任範囲がアーキテクチャ上で明確 解決策②-1:復旧時のバースト負荷を吸収 ● キューイングで再処理の負荷を平準化 解決策②-2:更新失敗の影響を局所化 ● 復旧後キューの内容に基づき再処理可能 59

60.

イベント駆動型の採⽤判断基準 ● イベント駆動の採⽤可否は、処理結果の即時確認が必要かどうかを主な判断軸とする。 更新結果の 即時確認が必要 な処理は、 API連携 が向いている 具体的には、処理の成否をその場で確認し、エラー時に即座に対応する必要がある場合 ● 例)即時の入金・出金処理 更新結果の 即時確認が不要 な処理は、 イベント駆動 が向いている 具体的には、⾮同期で処理でき、失敗時もリトライで対応できる場合 ● 例)外部サービスへの連携、メール送信 © WealthNavi Inc. All Rights Reserved. 60

61.

ウェルスナビでイベント駆動型(Pub/Sub 連携)採⽤に⾄ったケースを紹介 背景‧要求 ● ● ● 社内システムの業務処理が完了次第、社外へデータを連携したい Internalなシステムから外部へ直接リクエストを⾶ばすのは避けたい ⼀部のデータに誤りがあっても、他のデータ連携は確実に継続したい 解決策 ウェルスナビバックエンドにおいて習熟度の⾼い技術‧サービスを採⽤。 Amazon SNS、SQSを⽤いたPub/Sub 連携の仕組みを導⼊(後述)。 SNS → SQS 構成では、複数バックエンドへの fan-out による拡張性も確保できる。 © WealthNavi Inc. All Rights Reserved. 61

62.

Spring Cloud AWSを活⽤したイベント駆動アーキテクチャ 1. イベント駆動アーキテクチャ採⽤の動機付け 2. Pub/Subの概念とAWSでの構成 3. Spring Cloud AWSによる実装詳細 4. 運⽤‧設計上の考慮事項 © WealthNavi Inc. All Rights Reserved. 62

63.

イベント駆動を実現する Pub/Sub の概念を改めて紹介 Pub/Sub とは、イベントを送る側(Publisher)が仲介役(Message Broker)に イベントを送出し、イベントを受け取る側(Subscriber)がMessage Broker内の ⼀時的な蓄積場所(Queue)からメッセージを受け取って処理するアーキテクチャ Message Broker     Publisher Event Queue Subscriber イベントの送出元 メッセージの分類 ⼀時的な蓄積 イベントの受信‧処理 データの流れ © WealthNavi Inc. All Rights Reserved. 63

64.

AWSでPub/Subを構成する場合のアーキテクチャ AWSでの実践事例(ウェルスナビの場合) Publisher/Subscriberにはコンテナランタイム(Amazon ECS)を活⽤する Topic、Queueの管理にはAmazon SNS、SQSをそれぞれ活⽤する Message Broker    ECS SNS SQS Publisher Topic管理 Queue管理  ECS Subscriber データの流れ © WealthNavi Inc. All Rights Reserved. 参考:https://www.docswell.com/s/WN_Tech-PR/KPG18L-2025-11-20-154347#p18 64

65.

AWSでPub/Subを構成する場合のアーキテクチャ AWSでの実践事例(ウェルスナビの場合) Publisher/Subscriberにはコンテナランタイム(Amazon ECS)を活⽤する Topic、Queueの管理にはAmazon SNS、SQSをそれぞれ活⽤する Message Broker どうやってPublish する?  どうやって Subscribeする?   ECS SNS SQS Publisher Topic管理 Queue管理  ECS Subscriber データの流れ © WealthNavi Inc. All Rights Reserved. 65

66.

Spring Cloud AWSを活⽤したPub/Sub実装 Spring Cloud AWSとは AWS のメッセージングサービスを Spring から利⽤しやすくするライブラリ SNS / SQS を⽤いたイベント駆動アーキテクチャ導⼊時の開発効率向上が期待できる Message Broker Spring Cloud AWSを利用して Publish  Spring Cloud AWSを利用して Subscribe   ECS SNS SQS Publisher Topic管理 Queue管理  ECS Subscriber データの流れ © WealthNavi Inc. All Rights Reserved. 66

67.

Spring Cloud AWSを活⽤したイベント駆動アーキテクチャ 1. イベント駆動アーキテクチャ採⽤の動機付け 2. Pub/Subの概念とAWSでの構成 3. Spring Cloud AWSによる実装詳細 4. 運⽤‧設計上の考慮事項 © WealthNavi Inc. All Rights Reserved. 67

68.

利⽤バージョン Spring Framework / Spring Boot Java 25 v4.0.5 Spring Cloud AWS v4.0.2 implementation 'io.awspring.cloud:spring-cloud-aws-dependencies' © WealthNavi Inc. All Rights Reserved. 68

69.

Spring Boot で SNS へ Publish する⽅法 SnsTemplate を利⽤して、SNS Topic にメッセージを Publish する ● Publisher は 連携先の SQS Queue を意識しない ● Topic へのイベントは SNS Subscription が各 SQS Queue に配送する ● 連携先が増えても、Publisher 側の実装変更を抑えやすい © WealthNavi Inc. All Rights Reserved. 69

70.
[beta]
Spring Boot で SNS へ Publish する⽅法(サンプルコード)
SnsTemplate.sendNotification で SNS へ Publish する。
シリアライズ⽤のDTOクラスを作成する(Java 17以降であれば record を使⽤可能)。

●
●

PublishするServiceクラス

DTOクラス
public record NotificationMessage(

@Service

String eventId,

public class MessagePublisher {

String orderId,
private final SnsTemplate snsTemplate;

String customerId,

private final SnsProperties snsProperties;

String orderStatus,
String occurredDate

public void publish(NotificationMessage message) {
snsTemplate.sendNotification(
snsProperties.topicArn(), // Properties クラスを使用(※)

) {}

Properties クラス

message,

@ConfigurationProperties(prefix =

message.orderStatus());

"aws.sns")

}
}

public record SnsProperties(String
topicArn) {}

(※)参考:https://zenn.dev/khoshihara/articles/c05f10f2d4a936
© WealthNavi Inc. All Rights Reserved.

70

71.

Spring Boot で SQS を Subscribe する⽅法 @SqsListener を利⽤して、SQSのメッセージを Subscribe する ● アプリケーションは @SqsListener で SQS Queue をSubscribeする ● 処理に成功したメッセージは削除され、失敗した場合は再配信される © WealthNavi Inc. All Rights Reserved. 71

72.

Publisher と Subscriber の処理特性の違い 処理特性 Publisher Subscriber SNS へのシンプルなリクエストのみを⾏う 共通処理の実装が要求される ● ポーリング ● メッセージ取得、削除 ● 例外発⽣によるリトライ(DLQ移動の起点) 解決策 @SqsListener では、アノテーション付与のみで上記の共通処理を⾃動化 © WealthNavi Inc. All Rights Reserved. 72

73.

@SqsListenerを⽤いた処理フロー(正常系) ● @SqsListenerで指定したキューに対応する業務ロジックが正常終了するとメッセージが 削除される。 Queue (SQS) 正常系 EventHandler (@SqsListener) Service (@Service) DLQ (SQS) ①:ポーリング ②:業務ロジック ③:処理成功 ④:メッセージ削除 インフラ アプリ 処理の流れ © WealthNavi Inc. All Rights Reserved. 73

74.

@SqsListenerを⽤いた処理フロー(異常系) ● 処理中に例外(Exception)が maxReceiveCount を超えて発⽣すると、メッセージが DLQに移る。 Queue (SQS) 異常系 EventHandler (@SqsListener) Service (@Service) DLQ (SQS) ①:ポーリング ②:業務ロジック ④:メッセージは削除 しない ③:例外発⽣ ⑤:①~④のループが maxReceiveCount を超えると DLQ へ移る インフラ アプリ 処理の流れ © WealthNavi Inc. All Rights Reserved. 74

75.
[beta]
Spring Boot で SQS を Subscribe する⽅法(サンプルコード)
@SqsListener でキュー名を指定して Subscribeし、メッセージ取得後は業務処理を実⾏
する。

●

Handlerの実装(@Component)

Serviceクラス

@Component

@Service

public class MessageListener {

public class NotificationService {
public void

private final ObjectMapper objectMapper;
private final NotificationService notificationService;

process(NotificationMessage
message) {

@SqsListener("${aws.sqs.queue-name}")

// 例:業務処理を書く

public void receive(String rawMessage) throws Exception {

// 例:DB更新、データ連携など
}

// 例外が発生した場合はメッセージが削除されず、リトライ後に DLQ へ送出される(※)
NotificationMessage message = objectMapper.readValue(rawMessage,

}

NotificationMessage.class);
notificationService.process(message);
}
}

(※)参考:https://zenn.dev/khoshihara/articles/327df58984b44b
© WealthNavi Inc. All Rights Reserved.

75

76.

Spring Cloud AWSを活⽤したイベント駆動アーキテクチャ 1. イベント駆動アーキテクチャ採⽤の動機付け 2. Pub/Subの概念とAWSでの構成 3. Spring Cloud AWSによる実装詳細 4. 運⽤‧設計上の考慮事項 © WealthNavi Inc. All Rights Reserved. 76

77.

SQSの標準キュー‧FIFOキューの違いについて 標準キュー FIFOキュー ● ⾼スループットなメッセージ処理に最適 ● メッセージの順序性が重要な処理に最適 ● 重複配信、順序の前後が発⽣する可能性あり ● MessageGroupId 単位で順序が保証 ● 重複を抑制する仕組みを内蔵 ● 同⼀ MessageGroupId は直列化されるた め、スループット設計に注意 FIFOキューで高スループットが要求さ れる場合は、High Throughput FIFO を使用する(※)。 (※)https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/enable-high-throughput-fifo.html © WealthNavi Inc. All Rights Reserved. 77

78.

今回のユースケースでは重複を抑制できる点を評価しFIFOキューを選択 標準キュー FIFOキュー ● ⾼スループットなメッセージ処理に最適 ● メッセージの順序性が重要な処理に最適 ● 重複配信、順序の前後が発⽣する可能性あり ● MessageGroupId 単位で順序が保証 ● 重複を抑制する仕組みを内蔵 ● 同⼀ MessageGroupId は直列化されるた め、スループット設計に注意 © WealthNavi Inc. All Rights Reserved. 78

79.

デッドレターキュー(DLQ)の役割を紹介 DLQの役割 ● 処理に失敗し続けるメッセージを分離する⼿段 ● 失敗メッセージを調査し、原因特定‧再処理につなげる ● 障害検知の起点として 監視ツール(Datadog など)と組み合わせる © WealthNavi Inc. All Rights Reserved. 79

80.

デッドレターキュー(DLQ)の設計要素を整理 maxReceiveCount Visibility Timeout 何回失敗したら DLQ に送るか 1回の処理に必要な最⼤時間 Message Retention Redrive DLQ上で何⽇保持するか 修正後に元キューへ戻す⽅法を決める 監視 調査 DLQにメッセージが⼊ったら検知する メッセージを特定する⼀意なIDを設定する © WealthNavi Inc. All Rights Reserved. 80

81.

Pub/Subのテストについて Pub/Subのテストでは、ユニットテストに加え、 Integration テストも実施する テスト観点 Publisher Subscriber ユニットテスト SnsTemplate をモックし、送信引数を 検証 メッセージを受け取り、期待した処理 が実⾏されるか Integration テスト (LocalStack) LocalStack上のSNSへ Publishし、 SQSに流れたメッセージ内容を検証 LocalStack上のSQSに直接メッセージ を投⼊し受信、業務処理を検証(※) Message定義の検証 record クラスで定義し、 Publisher/Subscriber 双⽅で検証 同左 (※)参考:https://zenn.dev/khoshihara/articles/11954bcbb42aef © WealthNavi Inc. All Rights Reserved. 81

82.

Enjoy Spring Cloud AWS! © WealthNavi Inc. All Rights Reserved. 82

83.

4 1 まとめ © WealthNavi Inc. All Rights Reserved. 83

84.

まとめ 本セッションの振り返り 1 背景:データ連携⽅式の標準化の要求 3 AWS SNS/SQSを活⽤したPub/Subの実装 2 Spring Cloud Gateway によるAPI Gateway実装 今後はデータ連携⽅式の標準化とエコシステムを 開発組織全体に提供する取り組みを進めていきます。 本⽇はご静聴ありがとうございました! © WealthNavi Inc. All Rights Reserved. 84

85.

We are hiring 採⽤強化中 安⼼して使える⾦融インフラを共につくる仲間募集 https://recruit.wealthnavi.com/ © WealthNavi Inc. All Rights Reserved. 85

86.

重要な注意事項 ● 本資料は、断定的判断を提供するものではなく、情報を提供することのみを目的としており、いかなる種類の商品も勧誘 するものではありません。最終的な決定は、お客様自身で判断するものとし、当社はこれに一切関与せず、また、一切の 責任を負いません。 ● 本資料には将来の出来事に関する予想が含まれている場合がありますが、それらは予想であり、また、本資料の内容の 正確性、信頼性、完全性、適時性等を一切保証するものではありません。本資料に基づいて被ったいかなる損害について も、当社は一切の責任を負いません。また、当社は、新しい情報や将来の出来事その他の情報について、更新又は訂正 する義務を負いません。 ● 本資料を利用することによりお客様に生じた直接的損害、間接的損害、派生的損害その他いかなる損害についても、当社 は一切の責任を負いません。 商号等:ウェルスナビ株式会社 金融商品取引業者 関東財務局長(金商) 第2884号 加入協会:日本証券業協会 一般社団法人資産運用業協会 © WealthNavi Inc. All Rights Reserved. 86