JSUG勉強会 2017年その7 〜 俺たちのマイクロサービス に行ってきた #jsug

JSUG勉強会 2017年その7 に行ってきました。簡単に所感をまとめます。

jsug.doorkeeper.jp

今回のテーマはマイクロサービスです。メモから抜粋します。

無理をしないマイクロサービス

  • マイクロサービスアーキテクチャは手段
  • 組織や体制に合うやり方でこれまで実現できなかったことを実現する

    • やり方はそれぞれ違う
  • 各チームの機能追加を独立でデプロイできるようにする

  • リリーススピードを上げることが目的

  • よくあるアーキテクチャ

    • フロントエンドUI <–> サービスA, B, C, …
    • フロントエンドUI <–> API Gateway <–> サービスA, B, C, …
  • フロントエンドUIに変更が集中する

  • 各サービスがUIを持ち、各チームで開発する

  • ユーザ情報をどうやって連携するか

    • ユーザサービスを立ててSSOにする
    • 認証情報は Cookie に保存する
    • 各サービスはサブドメインで分ける
    • 昔からあるSSOのやり方
  • Cookie には JWT (JSON Web Token) で保存する
    • ..
    • Base64エンコードしてCookieに保存する
    • クライアント側はデコードするだけで使える
    • なりすまし防止のため、Header と Claims を秘密鍵で署名する (Signature)
    • 各サービスに公開鍵を渡しておく
  • Spring Security

    • JWT を公開鍵で検証、Base64 でデコードして Spring Security の UserDetails を生成する
    • Cookieがなければユーザサービスのログイン画面を表示する
  • 各サービスの画面レイアウトを統一したい

    • レイアウトを管理するチームを用意する
    • 共通レイアウトを jar でパッケージングして配布する
    • src/resources/templates/layout.html
  • aタグのURIはプロパティから取得する

    • 全サービスでプロパティのコピペが発生する
    • 共通化する (共通化し過ぎると独立してデプロイし辛くなるため、独立性を妨げない程度に共通化する)
    • Spring Cloud Config
    • Config Server で管理する
  • 他のサービスとの連携はAPI化する

    • どこかのAPIで障害が発生したときに呼び出し元に障害が伝搬する
  • Circuit Breaker
    • 障害の伝搬を防ぐ (fail fast)
      • アクセスできないようにする
    • 自動で復旧する
    • fallback が書ける
  • Spring Cloud Netflix (Hystrix)
  • それぞれのAPI呼び出しに Circuit Breaker を入れる
    • それぞれで HystrixCommand を書くのは煩雑
  • 中間に API Gateway を入れる
    • 各サービスは API Gateway を経由して各APIを利用する
    • fallback をここに書く
  • Zuul / Zuul2

  • Service Discovery

  • Envoy

    • サイドカーパターン
    • C++ベースのリバースプロキシ
    • サービスの代わりに Envoy 同士が連携して Service Mesh を構成する
    • Service Mesh の管制塔の役割として Istio がある
  • API呼び出しで必要となる入出力クラスをどうするか

    • 共通ライブラリにはしない (他チームの変更の影響を受けやすい)
    • 各サービスで必要なフィールドだけを定義したクラスを用意する
    • JSONをそのまま使う
    • API提供側がクライアントライブラリを配布する
  • プラットフォーム

    • k9s, Cloud Foundry
    • Spring Boot なら Docker コンテナを使う必要性はあまりないかも
      • jar自体がjavaコマンドで起動できるしポータブルなので
  • CI/CD

    • ビルド/デプロイの自動化
    • Concourseのパイプライン

俺のマイクロサービス -マイクロサービスに関する経験と考察-

  • 問題意識をベースにすることが大事
  • 誰かの真似ではない

  • マイクロサービスは、設計、実装、デプロイ、運用など多岐に亘る概念である

  • 結果論
  • グッドプラクティスに名前を付けたものがマイクロサービス
  • マイクロサービスの目的はスケーラビリティとアジリティを向上すること

    • それが必要な企業は決して多くはない
    • 多くの企業にとってはマイクロサービスは必要ではないかも
  • HTML5 + API

    • APIが再利用できない問題
    • 画面デザイン > API の順番で作ると、特定画面向けのAPIになってしまう
  • 深夜リリース

  • Start simple, not small

  • Spring Boot

    • Executable JAR == マイクロサービス
    • デプロイの局所化、Spring Cloud との連携が可能
  • Service Discovery + Load Balancing
    • Eureka
    • Spring Boot と組み合わせやすい
  • Queuing
  • Session Replication
    • スティッキーセッション
    • Spring Session + Hazelcast (ライトスルーができる)
  • Versioned Platform
    • サービスごとに言語やフレームワークが選べる
    • ノウハウの分散が懸念
    • 親pomでフレームワークのバージョンを統一する
    • Spring IO Platform の親pomを使う
      • 今は使っていない
      • バージョンアップ待ちがボトルネックになることも
    • 管理されたマイクロサービス
  • Shared Interface
    • サービス側の変更によってコンシューマ側の実装を変更しないといけない
    • サービス側とコンシューマ側で同じBeanを実装するのは無駄
    • 共通のインタフェース
      • サービス側とコンシューマ側が使う
      • 同じようなコンシューマの実装があちこちに
    • 実際はクライアントライブラリのアプローチをとった
      • 共通インタフェースやBeanもクライアントライブラリに入れる
  • Service Unit Test
    • 各サービスの Controller 以降を JUnit でテスト
      • DBアクセスを含めたテスト
    • 他のマイクロサービスの呼び出しはモックにする
      • Mockito などは使わず、オーバーライドでモックする
    • Spring Boot の機能で end-to-end を JUnit でテスト
  • Service Integration Test
    • マイクロサービスごとを結合するテストは必要
    • 各サービスを手動で立ち上げて JUnit から HTTP 通信でテストする
    • 正常系と異常系の数パターンをテストする
    • エラーの発生を正しく伝搬できるか確認する
    • インタフェースの齟齬は意外と多い
  • CI/CD
    • デプロイ数/対象が多すぎて手動だと大変、サーバの準備も大変
    • 環境構築を自動化する
    • 環境構築は Ansible で自動化
    • ビルドは Jenkins で自動化
    • 将来的にはブルーグリーンデプロイを目指したい
    • APIのバージョニングも大事 (初期段階から考慮する)
  • Monitoring
    • 監視は大事
    • Elasticsearchを中心としたモニタリングの仕組み
    • メトリクスやログの収集
    • Metricbeat, Filebeat, …
  • Front Service & Backend Service
  • Serverless
  • Shared Data Store
    • マイクロサービスごとに Data Store を用意する
    • マイクロサービス間で Data Store を共有する
    • KVS
  • Event Sourcing
    • 例) 買い物かご (商品追加、削除、空にする、など)
    • 買い物かごにイベントを発生させる
    • イベントの種類に商品追加、削除、空にする、などのイベントがある
    • 発生したイベントはすべて記録する
    • イベントの積み重ねによって買い物かごの状態を判断する
    • 状態のソーシングではなくイベントのソーシング
    • 処理の追い越しや不正な画面遷移が発生た場合にどう対処するか

これが正直な感想ではあります。あとマイクロサービスの起原は以下のブログです。(たぶん)

martinfowler.com

日本語訳はこれ。

kimitok.hateblo.jp

これを読むとマイクロサービスはあくまでも「結果論」であることが分かります。まずは、自分たちが解決したい問題や課題はなにか、これを明確にする必要があります。マイクロサービスは手段であり目的ではないわけです。

初期段階からマイクロサービスアーキテクチャを見据えることは大事だと思います。が、マイクロサービスは最先端の開発手法だから取り入れていくべきだ、みたいなひとたちはまだまだたくさんいると思います。先日、某大企業のセミナー資料にもそんなニュアンスのことが書かれていて、ちょっと残念な気持ちになりました…。

最後に Spring Fest 2017 の告知がありました。2017/11/24 開催です。

springfest2017.springframework.jp