microservices
アーキテクチャについて、アンチパターンや、思想を学んだ。
そこで実際にmicroservices
アーキテクチャで構成されたアプリケーションを見て、実際のプラクティスを学ぶ。
参考にするリポジトリ
- pivotalのトレーダーシステムのリポジトリを参考に、実際のアプリケーション実装を見ていく。
全体構成
cloud-foundry
をアプリケーション起動環境としていますが、構成で重要なのは以下の点が大事かなと。
-
全サービスが
Eureka
でservice-discovery
を実現。- アプリケーションの機能がステートレスになっているはず。(特定のサービスは特定の銘柄の情報だけを処理する!とかになっていない)
-
全サービスが
Spring-cloud-config
で設定ファイルの中央集権的な管理を実現。 -
Histrix
で「障害の伝播」を考慮。 -
web
サービスはエンドユーザがアクセスするサービスのため、SpringSecurity
でセキュリティ考慮。 -
各サービスは別リポジトリで管理されている。
実装を覗いてみる
とりあえず色々やってるweb
サービスを覗いてみる。
設定ファイル
spring:
application:
name: web-service
main:
allow-bean-definition-overriding: true
profiles:
active: local
info:
build:
group: ${group}
name: ${name}
description: ${description}
version: ${version}
-
Spring-cloud
はbootstrap
コンテキストをapplication
コンテキストの親的な立ち位置で扱えるようにしてあるみたい。で、それのデフォルト設定をbootstrap.yml
に記載すると起動時にロードするという仕組み。bootstrap.yml
はapplication.yml
よりも先に読まれる。 - このリポジトリには
application.yml
は存在せず、bootstrap.yml
のspring
タグの設定値を参照して、ConfigServer
からapplication.yml
をロードしてくるんだと思う。 -
ConfigServer
のURIとかないなあと思ってたら、cloud-foundry
のサービスでごにょごにょやってるらしい。ローカルでセットアップする場合は以下を記載したconfigserver.yml
としてConfigServer
のディレクトリに含めろって書いてた。
spring:
profiles:
active: git
cloud:
config:
server:
git:
uri: https://github.com/pivotalbank/cf-SpringBootTrader-config.git
つまり、起動時は以下のようにconfigが設定される。
web
リポジトリのbootstrap.yml
→configserver
URIのGitリポジトリのweb-service.yml
で、設定値を変えたい場合はアプリを再デプロイせずとも、configserver
のURIのGitリポジトリのymlファイルを更新すれば動的に設定を更新できる。
Application起動クラス
package io.pivotal.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
@EnableScheduling
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
static {
HostnameVerifier allHostsValid = (name, sslSession) -> true;
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}
-
@EnableDiscoveryClient
はこのアプリケーションをEureka
の管理するサーバに登録するためのアノテーション。 -
@EnableCircuitBreaker
はこのアプリケーションにHistrix
をサーキットブレーカとして登録する事を示すアノテーション。@HystrixCommand
で指定したフォールバックメソッドを実際の処理の代わりに返すようになる。
最後に
Spring-cloud
でMicroservices
アーキテクチャを実現するとこういう感じになるのかあ、と何となく理解できた。そしてNetflix
さんのOSSはMicroServices
アーキテクチャ実装するときにはお世話になるなあって感じ。
以下の点が気になった。
-
Spring-cloud-config
による動的設定変更と、中央集権的管理。これは是非やりたいけど、ConfigServer
が単一障害点にならないようにしたい。 -
Eureka
はアプリケーション起動時にDNS登録(みたいな事)をアノテーション一つで自動で行うから、自前でスクリプト組んでごにょごにょとかしなくて良いのは魅力的。でもAWS
のマネージドサービスとかでも代替できるのかも? - 同じクラス名だけどフィールドの違うドメインモデル(振る舞い持ってなかったからドメインモデルではないけど、
domain
パッケージに入ってた)をそれぞれの各サービスに持ってた。commonDomainModel
みたいなjar
に切り出して使うサービスの依存に含めるとかはしてなかった。jar
切り出しパターンであれば、ドメインモデルに振る舞いを持たせたときにweb
では使うメソッドだけど、account
では使わないメソッドとか生まれそうで、こっちのが好ましいなと思った。 - サービス間の疎通に
Webflux
の非同期HTTP-apiを使用していた。結局これリクエストの来たサービスの経路を通って、web
に返しているだけなので、ここを最短ルートで返すとかしてやると、もっと最適化される?でもそれってコンテキスト跨いだ処理をどこかに書かなきゃいけなくなるか?
気になる点は色々あるが、自分でも実装いじってみようと思います。