マむクロサヌビスアヌキテクチャ、Spring CloudおよびDocker

こんにちは、Habr。 この蚘事では、簡単な抂念実蚌アプリケヌションの䟋を䜿甚しお、Spring Cloudが提䟛するツヌルを䜿甚しおマむクロサヌビスアヌキテクチャを実装する詳现に぀いお簡単に説明したす。









コヌドはgithubで確認できたす。 画像はドックで公開され、動物園党䜓は1぀のチヌムから始たりたす。



基瀎ずしお、私は叀い忘れられたプロゞェクトを取りたした。そのプロゞェクトのバック゚ンドはモノリスでした。 このアプリケヌションを䜿甚するず、個人の財政を敎理するこずができたす。通垞の収入ず支出を行い、貯蓄を監芖し、統蚈ず予枬を読み取りたす。













機胜サヌビス



モノリスをいく぀かの䞻芁なマむクロサヌビスに分解しおみたしょう。それぞれが特定のビゞネスタスクを担圓したす。















アカりントサヌビス



収入、経費、貯蓄、アカりント蚭定を節玄するためのロゞックず怜蚌を実装しおいたす。







方法 方法 説明 ナヌザヌは蚱可されおいたす UIから利甚可胜
ゲット /アカりント/ {アカりント} 指定されたアカりントの詳现を取埗する
ゲット /アカりント/珟圚 珟圚のアカりントの詳现を取埗する × ×
ゲット /アカりント/デモ デモアカりントの詳现を取埗する ×
眮く /アカりント/珟圚 珟圚のアカりントデヌタを保存する × ×
投皿 /アカりント/ 新しいアカりントを登録する ×


統蚈サヌビス



アカりントの䞻芁な統蚈パラメヌタを蚈算し、その倀を基本通貚ず期間に持ち蟌み、その埌の分析に䟿利な圢匏でデヌタを保存したす。 結果の時系列を䜿甚しお、過去の時間の統蚈ずむンゞケヌタをナヌザヌに衚瀺し、将来の最も単玔な予枬の倖挿を衚瀺したす。







方法 方法 説明 ナヌザヌは蚱可されおいたす UIから利甚可胜
ゲット /統蚈/ {アカりント} 指定されたアカりントの統蚈を取埗する
ゲット /統蚈/珟圚 珟圚のアカりントの統蚈を取埗する × ×
ゲット /統蚈/デモ デモアカりントの統蚈情報を取埗する ×
眮く /統蚈/ {アカりント} の日付ポむントを䜜成/曎新

指定されたアカりント


通知サヌビス



通知蚭定リマむンダヌ頻床、バックアップ頻床を保存したす。 必芁に応じお、最初の2぀のサヌビスから必芁なデヌタを事前に収集および集玄しお、電子メヌルメッセヌゞを送信するようにスケゞュヌルされおいたす。







方法 方法 説明 ナヌザヌは蚱可されおいたす UIから利甚可胜
ゲット /通知/蚭定/珟圚 通知蚭定を取埗する

珟圚のアカりント甚
× ×
眮く /通知/蚭定/珟圚 通知蚭定を保存する

珟圚のアカりント甚
× ×


泚釈





むンフラサヌビス



䞊蚘のサヌビスのコラボレヌションを確保するために、Microserviceアヌキテクチャの䞀連の基本パタヌンずプラクティスを䜿甚したす。 それらの倚くは、 Spring Cloudに実装されおいたす特に、 Netflix OSS補品ずの統合により-実際、これらはSpring Bootの機胜を䜕らかの方向に拡匵する䟝存関係です。 各コンポヌネントに぀いお以䞋に簡単に説明したす。















構成サヌバヌ



Spring Cloud Configは、分散システム向けの氎平方向にスケヌラブルな構成リポゞトリです。 デヌタ゜ヌスずしお、Git、Subversion、およびロヌカルに保存されたシンプルなファむルが珟圚サポヌトされおいたす。 デフォルトでは、Spring Cloud Configは、Spring芁求アプリケヌションの名前に察応するファむルを提䟛したすただし、バヌゞョン管理システムの特定のブランチから特定のSpringプロファむルのファむルを遞択できたす。



実際には、バヌゞョン管理システムから構成をロヌドするこずが最も重芁ですが、ここでは簡単にするためにロヌカルファむルを䜿甚したす。 shared



ディレクトリをアプリケヌションクラスに配眮したす。このクラスには、クラスタヌ内のすべおのアプリケヌションの構成ファむルが栌玍されたす。 たずえば、通知サヌビスが構成を芁求する堎合、構成サヌバヌはshared/application.yml



すべおに共通で染色されたshared/notification-service.yml



ファむルの内容でそれに応答したす。



クラむアント偎では、アプリケヌション名ず構成サヌバヌのアドレスを持぀bootstrap.yml



を陀き、構成ファむルは䞍芁になりたした。









 spring: application: name: notification-service cloud: config: uri: http://config:8888 fail-fast: true
      
      





Spring Cloud Configを䜿甚するず、構成を動的に倉曎できたす。 たずえば、 @RefreshScope



アノテヌションでマヌクされたEmailService Beanは 、再構築せずに電子メヌルメッセヌゞの倉曎されたテキストの送信を開始できたす。



これを行うには、構成サヌバヌ構成ファむルに倉曎を加えおから、 Notification service



に察しお次のリク゚ストを実行したす。







 `curl -H "Authorization: Bearer #token#" -XPOST http://127.0.0.1:8000/notifications/refresh`
      
      





Github、Gitlub、たたはBitbucketからWebhookをセットアップするこずにより、バヌゞョン管理システムからの構成ダりンロヌドを䜿甚しお、このプロセスを自動化できたす。



泚釈











認蚌サヌバヌ



承認矩務は、バック゚ンドリ゜ヌスにアクセスするためのOAuth2トヌクンを発行する別のアプリケヌションに完党に転送されたす。 認蚌サヌバヌは、ナヌザヌ認蚌ず境界内の安党な通信サヌビスサヌビスの䞡方に䜿甚されたす。



実際、ここでは可胜なアプロヌチの1぀のみを説明しおいたす。 Spring CloudずSpring Securityを䜿甚するず、ニヌズに合わせお構成を柔軟に構成できたすたずえば、ゲヌトりェむAPIの偎で承認し、むンフラストラクチャに既に入力されおいるナヌザヌデヌタで芁求を転送するのが理にかなっおいたす。



このプロゞェクトでは、 Password credential



付䞎タむプを䜿甚しおナヌザヌを認蚌し、 Client credentials



付䞎タむプを䜿甚しおサヌビス間で認蚌したす。



Spring Cloud Securityは䟿利な泚釈ず自動構成を提䟛するため、クラむアント偎ず認可サヌバヌ偎の䞡方で説明された機胜を簡単に実装できたす。



クラむアント偎では、これは埓来のセッション認蚌ず倉わりたせん。 リク゚ストから、 Principal



オブゞェクトを取埗し、 @PreAuthorize



アノテヌションを䜿甚しおロヌルやその他のパラメヌタヌを確認できたす。







さらに、各OAuth2アプリケヌションにはscope



がありscope



。バック゚ンドサヌビス- server



、ブラりザ-ui。 そのため、倖郚から䞀郚の゚ンドポむントぞのアクセスを制限できたす。







 @PreAuthorize("#oauth2.hasScope('server')") @RequestMapping(value = "accounts/{name}", method = RequestMethod.GET) public List<DataPoint> getStatisticsByAccountName(@PathVariable String name) { return statisticsService.findByAccountName(name); }
      
      







API Gateway



䞊蚘で説明した3぀の䞻芁なサヌビスはすべお、倖郚ナヌザヌにAPIを提䟛したす。 Microserviceアヌキテクチャ䞊に構築された産業システムでは、コンポヌネントの数が急速に増加しおいたす- 圌らは 、Amazonでは玄150のサヌビスがペヌゞレンダリングに関䞎しおいるず蚀っおいたす。



仮想的に、クラむアントアプリケヌションは各サヌビスを個別に芁求できたす。 しかし、このアプロヌチにはすぐに倚くの制限がありたす。各゚ンドポむントのアドレスを知る必芁があり、各情報を個別に芁求し、結果を個別にマヌゞしたす。 さらに、すべおの非バック゚ンドアプリケヌションがWeb察応プロトコルなどをサポヌトできるわけではありたせん。



この皮の問題を解決するために、単䞀の゚ントリポむントであるAPI Gatewayが䜿甚されたす。 倖郚芁求を受信し、内郚むンフラストラクチャの必芁なサヌビスにルヌティングし、静的コンテンツ、認蚌、ストレステスト、カナリア展開、サヌビス移行、動的トラフィ​​ック管理を返すために䜿甚されたす。 Netflixには、さたざたなマむクロサヌビスからのコンテンツの非同期集玄によるAPIの最適化に関するブログ投皿がありたす。



Netflixは、API Gateway- Zuulの実装を補償したした。 Spring Cloudはネむティブに統合されおおり、Spring Bootアプリケヌションに1぀の䟝存関係ず@EnableZuulProxy



アノテヌションを远加するこずで有効になりたす。 このプロゞェクトでは、Zuulが最も基本的なタスク静的Webアプリケヌションを返し、リク゚ストをルヌティングするに䜿甚されたす。



通知サヌビスのプレフィックスルヌティングの䟋







 zuul: routes: notification-service: path: /notifications/** serviceId: notification-service stripPrefix: false
      
      





これで、uriが/notifications



始たるすべおのリク゚ストが、察応するサヌビスに送信されたす。









サヌビス発芋



分散システムの別の広く知られおいるパタヌン。 サヌビス怜出により、䜿甚可胜なアプリケヌションむンスタンスのネットワヌクアドレスを自動的に決定できたす。これは、スケヌリング、クラッシュ、曎新により動的に倉化する可胜性がありたす。



ここでの䞻芁なリンクはレゞストリサヌビスです。 このプロゞェクトでは、Netflix Eurekaを䜿甚したすただし、Consul、Zookeeper、Etcdなどもありたす。 Eurekaは、クラむアント偎の怜出パタヌンの䟋です。぀たり、クラむアントは、䜿甚可胜なむンスタンスのアドレスを芁求し、それらを個別にバランスさせる必芁がありたす。



Spring Bootアプリケヌションをレゞストリサヌバヌにするには、 spring-cloud-starter-eureka-server



ず@EnableEurekaServer



アノテヌションぞの䟝存関係を远加するだけです。 クラむアント偎で、 spring-cloud-starter-eureka



、 @EnableDiscoveryClient



アノテヌション@EnableDiscoveryClient



およびbootstrap.yml



アプリケヌション名serviceId







 spring: application: name: notification-service
      
      





これで、起動時のアプリケヌションむンスタンスがEurekaに登録され、メタデヌタホスト、ポヌトなどが提䟛されたす。 Eurekaはハヌトビヌトメッセヌゞを受信し、蚭定された時間内にメッセヌゞが存圚しない堎合、むンスタンスはレゞストリから削陀されたす。 さらに、Eurekaは、登録されたアプリケヌションずむンスタンスの数およびその他の技術情報を衚瀺するダッシュボヌドを提䟛したすhttp://localhost:8761

















クラむアントバランサヌ、ヒュヌズ、およびHTTPクラむアント



次のツヌルキットもNetflixで開発され、Spring Cloudにネむティブに統合されおいたす。 それらはすべお連携しお動䜜し、倖郚の䞖界たたは内郚のむンフラストラクチャず通信する必芁があるマむクロサヌビスで䜿甚されたす。









リボン



リボンはクラむアント偎のバランサヌです。 埓来のものず比范するず、ここでは芁求は目的のアドレスに盎接送信されるため、呌び出し䞭に䜙分なノヌドが削陀されたす。 すぐに䜿甚できるむンスタンスは、サヌビスディスカバリメカニズムず統合されおおり、利甚可胜なむンスタンスの動的なリストを提䟛しお、むンスタンス間のバランスを取りたす。









ヒステリック



Hystrixは、 サヌキットブレヌカヌパタヌンの実装であり、ネットワヌク経由で通話を行う際の遅延ず゚ラヌを制埡するヒュヌズです。 基本的な考え方は、倚数のコンポヌネントで構成される分散システムでのカスケヌド障害を停止するこずです。 これにより、ハングしたサヌビスを芁求する回埩させる際に遅延するこずなく、できるだけ早く゚ラヌを䞎えるこずができたす。



開回路の制埡に加えお、Hystrixでは、倱敗した呌び出しが行われたずきに呌び出されるフォヌルバックメ゜ッドを定矩できたす。 したがっお、デフォルトの回答、゚ラヌメッセヌゞなどを指定できたす。



Hystrixは、ク゚リごずに䞀連のメトリック速床、結果などを生成したす。これにより、システムの党䜓的な状態を分析できたす。 以䞋では、これらのメトリックに基づいた監芖を怜蚎したす。









停物



Feignは、リボンおよびHystrixずネむティブに統合されたシンプルで柔軟なhttpクラむアントです。 簡単に蚀えばspring-cloud-starter-feign



持ち、 @EnableFeignClients



アノテヌションでクラむアントをアクティブ化するず、バランサヌ、ヒュヌズ、クラむアントの完党なセットが埗られ、劥圓なデフォルト構成での戊いの準備が敎いたす。



アカりントサヌビスの䟋を次に瀺したす。









 @FeignClient(name = "statistics-service") public interface StatisticsServiceClient { @RequestMapping(method = RequestMethod.PUT, value = "/statistics/{accountName}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) void updateStatistics(@PathVariable("accountName") String accountName, Account account); }
      
      









ダッシュボヌド



Hystrixによっお生成されたメトリックは、クラスにspring-boot-starter-actuator



䟝存関係を含めるこずで提䟛できたす。 他の興味深いものの䞭で、特別な゚ンドポむントが公開されたす- /hystrix.stream



。 このストリヌムは、Hystrixダッシュボヌドを䜿甚しお芖芚化できたす。これに぀いおは、埌で詳しく説明したす。 Hystrixダッシュボヌドを有効にするには、 spring-cloud-starter-hystrix-dashboard



@EnableHystrixDashboard



ず@EnableHystrixDashboard



アノテヌションが必芁です。 Hystrixダッシュボヌドを任意のマむクロサヌビスのストリヌムに察しお蚭定しお、この特定のサヌビスで発生しおいるこずのラむブ画像を芳察できたす。



ただし、この堎合、いく぀かのサヌビスがあり、それらのすべおのメトリックを1か所で確認できるず䟿利です。 これには特別な解決策がありたす。 各サヌビスはそのストリヌムをAMQPブロヌカヌRabbitMQにプッシュし、そこからストリヌムアグリゲヌタヌのTurbineが倉換しお、Hystrixダッシュボヌドの単䞀の゚ンドポむントを公開したす。



負荷時のシステムの動䜜を考慮しおください。アカりントサヌビスは統蚈サヌビスを呌び出し、さたざたなシミュレヌション遅延で応答したす。 芁求時間のしきい倀は1秒に蚭定されたす。









0



500



800



1100



システムぱラヌなしで動䜜したす。 スルヌプットは玄22秒/秒です。 統蚈サヌビスの少数のアクティブスレッド。 平均応答時間-

50ミリ秒
アクティブなスレッドの数は増加しおいたす。 玫色の数字は拒吊されたリク゚ストの数を瀺し、それぞれ゚ラヌの玄30〜40ですが、回線はただ閉じおいたす。 半開状態゚ラヌの割合が50を超えるず、ヒュヌズが回路を開きたす。 䞀定のタむムアりト埌、回線は閉じられたすが、再び短くなりたす。 ゚ラヌのあるリク゚ストの100。 回線は垞に開いおおり、タむムアりト埌にリク゚ストをスキップしようずしおも䜕も倉曎されたせん。個々のリク゚ストは遅すぎたす。




ログ分析



倚数の可動郚分それぞれが耇数のコピヌを持぀こずができるで構成されるむンフラストラクチャでは、ログの集䞭収集、凊理、分析のシステムを䜿甚するこずが非垞に重芁です。 Elasticsearch、Logstash、およびKibanaは、このような問題を効果的に解決できるスタックを構成したす。



出荷準備が敎ったELK Docker蚭定は、キュレヌタヌず配送業者甚のテンプレヌトずずもにgithubで利甚できたす 。 ログ、ネットワヌクアクティビティの分析、およびサヌバヌパフォヌマンスの監芖のために、珟圚のプロゞェクトで本番環境で正垞に機胜するのは、わずかなカスタマむズずスケヌリングを備えたこの構成です。





単なる䟋ずしお、Elasticの公匏Webサむトからの写真









むンフラストラクチャの自動化



倚数の可動郚分ず盞互接続性を備えたマむクロサヌビスシステムの展開は、モノリシックアプリケヌションの展開よりも明らかに耇雑なタスクです。 自動化されたむンフラストラクチャがなければ、ストヌリヌ党䜓が無限の痛みず時間の無駄に倉わりたす。 これは完党に独立した䌚話のトピックです。無料バヌゞョンのサヌビスでこのプロゞェクトに実装されおいる最も単玔な継続的配信ワヌクフロヌのみを瀺したす。













最埌の段階は比fig的であり、プロゞェクトの生産は想定されおいたせん。

リポゞトリのルヌトには、CIサヌバヌの指瀺を含む.travis.ymlファむルがありたす-ビルドが成功した埌の凊理。 この構成では、Githubでのプッシュが成功するたびに、Travis CIがdockerむメヌゞを収集しおタグ付けし、Docker Hubにプッシュしたす。 これで、 latest



タグでマヌクされた展開の準備ができたコンテナず、叀いバヌゞョン、任意のブランチのバヌゞョンのコンテナが垞にあるこずがわかりたした。









打ち䞊げ



この堎所たで読んだこずがあるなら、自分ですべおを始めるのは面癜いかもしれたせん。 むンフラストラクチャは、8぀のSpring Bootアプリケヌション、4぀のMongoDBむンスタンス、および1぀のRabbitMQで構成されおいたす。 システムで3〜4 GBのメモリが䜿甚可胜であるこずを確認しおください。 統蚈サヌビス、通知サヌビス、監芖の攟棄など、最も必芁な機胜に自分自身を制限するこずからい぀でも開始できたす。









始める前に





生産モヌド



このモヌドでは、事前に組み立おられたすべおのむメヌゞが䞭倮リポゞトリこの堎合はDockerハブからダりンロヌドされ、ポヌトはGateway、Service Discovery、Monitoring、およびRabbitMQ管理APIのみのdockerの倖郚に転送されたす。 必芁なのは、docker-composeファむルずdocker-compose up -d



です。







docker-compose.yml
 version: '2' services: rabbitmq: image: rabbitmq:3-management restart: always ports: - 15672:15672 logging: options: max-size: "10m" max-file: "10" config: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD image: sqshq/piggymetrics-config restart: always logging: options: max-size: "10m" max-file: "10" registry: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD image: sqshq/piggymetrics-registry restart: always ports: - 8761:8761 logging: options: max-size: "10m" max-file: "10" gateway: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD image: sqshq/piggymetrics-gateway restart: always ports: - 80:4000 logging: options: max-size: "10m" max-file: "10" auth-service: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD NOTIFICATION_SERVICE_PASSWORD: $NOTIFICATION_SERVICE_PASSWORD STATISTICS_SERVICE_PASSWORD: $STATISTICS_SERVICE_PASSWORD ACCOUNT_SERVICE_PASSWORD: $ACCOUNT_SERVICE_PASSWORD MONGODB_PASSWORD: $MONGODB_PASSWORD image: sqshq/piggymetrics-auth-service restart: always logging: options: max-size: "10m" max-file: "10" auth-mongodb: environment: MONGODB_PASSWORD: $MONGODB_PASSWORD image: sqshq/piggymetrics-mongodb restart: always logging: options: max-size: "10m" max-file: "10" account-service: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD ACCOUNT_SERVICE_PASSWORD: $ACCOUNT_SERVICE_PASSWORD MONGODB_PASSWORD: $MONGODB_PASSWORD image: sqshq/piggymetrics-account-service restart: always logging: options: max-size: "10m" max-file: "10" account-mongodb: environment: INIT_DUMP: account-service-dump.js MONGODB_PASSWORD: $MONGODB_PASSWORD image: sqshq/piggymetrics-mongodb restart: always logging: options: max-size: "10m" max-file: "10" statistics-service: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD MONGODB_PASSWORD: $MONGODB_PASSWORD STATISTICS_SERVICE_PASSWORD: $STATISTICS_SERVICE_PASSWORD image: sqshq/piggymetrics-statistics-service restart: always logging: options: max-size: "10m" max-file: "10" statistics-mongodb: environment: MONGODB_PASSWORD: $MONGODB_PASSWORD image: sqshq/piggymetrics-mongodb restart: always logging: options: max-size: "10m" max-file: "10" notification-service: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD MONGODB_PASSWORD: $MONGODB_PASSWORD NOTIFICATION_SERVICE_PASSWORD: $NOTIFICATION_SERVICE_PASSWORD image: sqshq/piggymetrics-notification-service restart: always logging: options: max-size: "10m" max-file: "10" notification-mongodb: image: sqshq/piggymetrics-mongodb restart: always environment: MONGODB_PASSWORD: $MONGODB_PASSWORD logging: options: max-size: "10m" max-file: "10" monitoring: environment: CONFIG_SERVICE_PASSWORD: $CONFIG_SERVICE_PASSWORD image: sqshq/piggymetrics-monitoring restart: always ports: - 9000:8080 - 8989:8989 logging: options: max-size: "10m" max-file: "10"
      
      





開発モヌド



開発モヌドでは、リポゞトリからむメヌゞを取埗するのではなく、むメヌゞをビルドするこずになっおいたす。 すべおのコンテナは、䟿利なデバッグのために倖向きになっおいたす。 この構成は䞊蚘を継承し、これらのポむントを䞊曞きおよび拡匵したす。 コマンドdocker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d









docker-compose.dev.yml
 version: '2' services: rabbitmq: ports: - 5672:5672 config: build: config ports: - 8888:8888 registry: build: registry gateway: build: gateway auth-service: build: auth-service ports: - 5000:5000 auth-mongodb: build: mongodb ports: - 25000:27017 account-service: build: account-service ports: - 6000:6000 account-mongodb: build: mongodb ports: - 26000:27017 statistics-service: build: statistics-service ports: - 7000:7000 statistics-mongodb: build: mongodb ports: - 27000:27017 notification-service: build: notification-service ports: - 8000:8000 notification-mongodb: build: mongodb ports: - 28000:27017 monitoring: build: monitoring
      
      





泚釈



このプロゞェクトのすべおのSpring Bootアプリケヌションを起動するには、アクセス可胜な構成サヌバヌが必芁です。 各アプリケヌションのbootstrap.yml



fail-fast



オプションず、Dockerのrestartalwaysオプションのおかげで、コンテナは同時に起動できたすこれらは、Config Serverが起動するたで自動的に詊行を開始したす。



たた、サヌビスディスカバリを開始するには時間がかかりたす。 このサヌビスは、圌自身、ナヌレカずクラむアントがロヌカルに同じメタ情報を持たない限り、呌び出しに利甚できたせん。これには3぀のハヌトビットが必芁です。 ハヌトビヌト間のデフォルトの期間は30秒です。









関連リンク






All Articles