せてぃーずノート

Javaのイベント参加レポートとかを書いたりします。

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

週末風邪で倒れてたので初投稿です。
教科書の話ではなく、実プロジェクトの経験ベースの貴重な発表がきけました。

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

資料は非公開。
実際にマイクロサービスを導入したときの話。

無理をしない

自分たちの体制や得意な技術に合うやり方で、これまでやりたくてもできなかったことをする。

実際にやったこと

  • 最初はBigMonolith。リリーススピードをあげたい

    • コンフリクトが発生すると解消に時間かかる
  • バックエンドをチーム毎に分割して、フロントエンドにUIサービスを置いてAPIで呼ぶ

    • フロントエンドのUIが全チームで共有するため、フロントエンドでコンフリクトが発生
  • コンポーネント指向のSPAやBFFは、サーバーサイドスキル中心のチームで採用するのは厳しい(無理をする)

  • 各サービスがUIまで持つ完結したアプリケーションの構成

    • 注文、カート、オーダーといったアプリケーションが画面遷移で繋がってる構成
  • ユーザー情報の連携はもともとあったSSOの仕組みを利用

    • cookieにJWTで暗号化したユーザー情報を保存してサブドメインで共有
    • PreAuthenticatedAuthenticationを利用して連携
  • リンクのURLはSpringCloudConfigで一括管理

    • 開発中とプロダクションで値の切替もできる
  • 他のサービスと連携する部分はAPI

  • API呼び出しで障害が発生すると、障害の連鎖で最悪LBがダウンする

    • 障害の連鎖を防ぐためのサーキットブレーカー(Hystrix)の導入
    • Fallbackが注目されがちだが、障害の発生したAPIにアクセスさせないことが重要な目的
  • APIにHystrixのアノテーションを書きたくないため、APIゲートウェイを導入しそこでサーキットブレーカーを設定

    • 各チームの作業コストは0
  • Zuul2の開発は停滞中。yamlで定義がかけるSpringCloudGatewayが開発進行中

  • サービスディスカバリーは使わず、Cloud FoundryのRouterを利用

    • Cloud FoundryではLB→ルーター→サービスという流れになるので、パフォーマンスを気にする場合はサービスディスカバリーを導入すべき
  • サービスディスカバリーの種類

    • 名前解決:DNS、REST
    • 提供方法:アプリ、プラットフォーム
    • EurekaはREST、アプリ
    • ConsulはDNS、アプリ
    • k8sはDNS、プラットフォーム
  • CloudFoundryもサービスディスカバリーをプラットフォームで提供する予定

    • アプリケーション側ではなく、プラットフォーム側でやるべき
  • 最近はEnvoyがホット

    • サービスメッシュを形成する
    • メッシュを管理するIstioもホット

envoyproxy.github.io

istio.io

  • APIでクラスを共有すると、サービス側の変更でクライアントも影響を受けるので、サービス側がクライアントを提供する

    • 破壊的変更がない限りは影響なし
  • k8sやCloudFoundryのようなXaaSを利用する

    • k8sはコンテナから先を実装するCaaS
    • CloudFoundryはコンテナやランタイム/ミドルウェアまでをプラットフォームが提供
  • Spring Bootはコンテナにする利点があまりないのでCloud Foundry

    • コンテナにしてもjava -jarをするだけ
  • CI/CDのパイプラインはconcourse

重要なこと

  • やりたいこと(これまでできなかったこと)が解決できているか
  • 技術を目的にしない

俺のマイクロサービス

  • マイクロサービスは目指すものではなく結果論
  • マイクロサービスには守破離の守がなく、こうやれば始められるというものがない

ECサイトの例

  • もともとはオフショアで作られたシステムで品質がひどい
  • HTML5+Java APIで作り直した

    • 既存システムに比べて安定したが問題も
  • APIが画面項目とひも付き、再利用できない

  • RDBの負荷が高い
  • Tomcatを再起動するとセッションが初期化されるため、誰もアクセスして来ないであろう深夜にしかリリースできない
  • 非同期処理がやっつけ

15のやったこと

1.SpringBootの導入

2.サービスディスカバリーとロードバランス

  • Eurekaを導入。サービスメッシュは検討中

3.キューイング

  • ファイルでやってたところを、オープンな仕様のAMQP(RabbitMQ)を導入
  • 今ならSpringCloudStreamとkafka使うかも

4.セッションレプリケーション

  • SpringSession+Hazelcastを利用。今の所は問題ないが、ヘビーに使い込んでないので、後ほど再評価したい

5.Versioned Platform

  • Sprong+Javaで統一し、親Pomを各サービスで共有

6.shared interface

  • 共通のインターフェースを提供し、コンパイルエラーで気付けるようにする
  • 便利だったけどMSAっぽくないと言われる

7.client library

  • 6はコンシューマーでインターフェースを実装しなければならず、同じコードがたくさんできて効率悪い
  • 実装したクライアントをサービス側で配布。コンシューマー側の実装が楽に。

8.service unit test

  • 各マイクロサービスは、Controllerに対してJunitテストを書く(必須)
    • 別サービスの呼び出しはモックにする。Mokitoとかつかわず、オーバーライド。
  • 複雑な計算等不安な部分は局所的に書く(任意)
  • Http通信の部分はSpringbootを利用
    • 正常系、異常系のJSONやバリデーションをテスト

9.Service integration test

  • サービス結合で期待したデータと違う等のインターフェース齟齬が発生し試験が進まなかった。
  • 複数のマイクロサービスを手動で立ち上げてテストする
    • 実行をjunitにしておけば残しておける
    • 数ケースだけでもかなり問題が検出できる(それくらいインターフェース齟齬が多かった)

10.CI/CD

  • AnsibleとJenkinsを利用して環境構築を自動化
  • APIのバージョニングをしていなかったので困っている。バージョニングはすごく重要

11.monitoring

  • 障害がユーザーからの問い合わせで発覚することが多く監視が必要
  • elasticsearchをつかって全サーバーのCPU、メモリ使用率、ディスク使用率やログを採取
  • ログは5分間でてないと異常と判断
    • 既存メッセージを取り除いて、未知のメッセージが出ているか調べる
  • 気づかれなければいいで片付けない。

12.Frontend service & backend service

  • 再利用できるバックエンド、再利用しない前提のフロント

13.serverless

  • AWS LambdaをPythonで利用
  • バッチや非同期処理で使っている。APIでは使ってない

14.separated data store

  • RDBMSだと1つのJSONを保存するのに8個のテーブルを更新しないと行けないばあいがある
  • 使いやすいKVSを探しているが見つからない

15.イベントソーシング

  • 買い物かごのAPIを、データベース視点のCRUDや追加・削除のようなビジネスロジック的なAPIではなくイベントを登録するAPIだけ提供

    • 商品を入れる、出すを全てイベントとして記録する。
  • データ不整合が発生しても、イベントなら何が原因かがトレースできる

  • 処理の追い越しや不正な遷移が発生したときの対応は検討が必要

これからやりたこと

  • サーキットブレーカー、リアクティブAPI、コンテナやプラットフォーム

感想とか

  • 手段を目的にしないことが大事

  • 自然と教科書の構成に近づいていく

    • 教科書的な構成に合わせなくてもいい
    • 自然と似てくる
  • サービスメッシュとか知らない言葉が増えてたので、常にトレースしていくのが重要

JSUGからのお知らせ

  • 11/24にSpringFest2017

    • 会場は両国KFCホール
    • 前回と同じく400〜500人の規模を想定
  • 来月の勉強会は10/27。会場は恵比寿のRedhat