by shigemk2

当面は技術的なことしか書かない

memo: モノリシックからリアクティブへ - 大切なのはアーキテクチャ(Java編) #reactive_shinjuku

https://reactive-shinjuku.connpass.com/event/49818/

  • @jroper
  • Lightbend
  • java/scala/akka
  • (デモはUbuntu/IntelliJ IDEAを使っている)

  • 横田さん補足付き英語プレゼン

アジェンダ

  • identify pitfalls of monolith conversions
  • モノリスを置き換える際の落とし穴とリアクティブなソリューションの設計
    • リプレイスはトレンド
    • いくつか落とし穴があるので、ちゃんと理解しないとモノリシックなシステムより悪いものができてしまう
    • そのための設計 godd pattern
  • Lagomをつかったデモ
    • Lagomだけではなく、どんなフレームワークにたいしてもリプレイスできるアプローチ
    • spring node.jsとか

Lagom Auction

  • eBayのクローンを目標とする
  • めざせeBay
  • eBayよりも良い物になっているはず

  • オークションサイト(感覚的にはヤフオクに近い)

    • 例: オークションとして自転車を出品する
    • 30秒でオークション終了
  • モノリシックな例: ぜんぶspring
    • MVC controllers/item model/bidding model
  • マイクロサービス: (Lagom)

    • web gateway/item service/bidding model
    • 素直な書き換え
  • more moving parts

  • more chance ofor failure
  • more chance for inconsistency

  • 可動部分が増えるので、バグが増えやすい

  • 負荷が起きた時の障害パターンの一貫性が崩れる(有名人が出品したときなど)

synchronous communication(同期性)

  • ナイーブな書き換え
  • それぞれのコンポーネント間のコミュニケーション
  • 両者が同じ時間を共有している それは問題になりうる
  • 両者が同時に即応できる必要性がある
  • リクエストを送ったそのときに受け取る側が起動していなければならない

  • system

    • 有名人の出品→リクエストやリフレッシュが増える→入力サービスの遅延→サービス全体の遅延
  • ジャスティン・ビーバー

    • 同期的通信→ひとつのところが遅くなるとほかのコンポーネントも遅くなる
    • シミュレーション
    • 人はブラウザ描画が遅くなるとリロードするので輻輳が起きて悪循環になる→最悪復帰もできない
  • サーキットブレーカー

    • 障害児にブレーカーを上げて障害を起こしたサービスを保護する
    • https://ja.wikipedia.org/wiki/サーキットブレーカー制度
    • 一般的なブレーカーと同じく、一定以上負荷が増えるとリクエスト自体を遅らせる
      • もしくは別のものを表示させる
  • lagom.circuit-breaker

failure recovery

  • 障害復旧 サービス品質を下げて障害をワークアラウンドする
  • レンダリングに必要なコンポーネントはいちぶ

  • degration(英語では良い意味としても使われる)

    • graceful degration
    • サービスを守るためにデグレーションを行う
    • 全員がすべてのサービスを求めているわけではない
    • e.g. billingはできないけどアイテム閲覧はできる
  • e.g. サーキットブレーカーの設定により、一定回数以上失敗したのでアイテムの閲覧しかできなくなっている
  • failure can lead to inconsistency

障害により失われる一貫性

  • 入札情報の伝搬 POST: startAuction WebGateway→ItemService→BiddingService という流れ
  • 同期通信は全員が生きているのが前提
    • bidding serviceが死んだとき
    • 他のコンポーネントもうまく情報共有できない
  • サービスをkillする
  • 同期通信で同時に更新をかけるのは危険であるので、サービスの境界をこえるトランザクションはできない
    • service boundaries
  • 同期通信で2つのサービスに同時更新は危険
  • トランザクションなので、片方が失敗したらもう片方はロールバックする ただしそれはマイクロサービスとはいえない マイクロサービスにトランザクションはない

  • 方策

    • 送った側と受け取る側が同時に起きていなくてもいい
    • イベントを永続したシステムにフィットする
    • event/state 状態の書き換え(state) 別々にイベントを永続化していく(event)
    • 非同期メッセージング すべてのシステムが同時に即応性を保つひつようはない
    • イベントを永続化してメッセージのソースとしてつかう
  • メッセージを非同期で伝える

  • bidding serviceに障害がおきてもよくて、復旧したらメッセージングを再開する(=オークションが再開する/biddingが処理される)

  • lagom/kafkaを使った例

    • 非同期通信ライブコーディング
    • Kafka/Topic/Offset/subscribe
    • akka streamのflow的な使い方

うまくいかないときのハンドリングをどうするか

  • 非同期処理ベースなので、どこかで悪いところが発生したばあいに自己回復している
    • 生き返ったときに一貫性のある状態まで回復できる

unacceptable degradation

  • 許容できないデグレード: 入札価格0ドルへのフォールバック(入札履歴が0件になるのはまだマシ)
  • graceful degradation/unacceptable degradation
    • biddingの履歴が見れないのは良いが、biddingの金額がゼロなのはユーザーに受け入れられない(混乱する)
    • ビジネス的な意味論でどんなデグレを許容するかを考える

denormalize

  • normalization(正規化)はDBの文脈でよくつかわれる

    • 複数のテーブルで同一カラムが存在しないようにする
  • 非正規化

    • 他のサービスに重要な情報を送り重複保存する
    • システムにとって重要な機能 vs ビジネスにとって重要な機能
    • ≒冗長化
  • web gatewayで得られた情報をitem serviceでも共有する→片方がおちてももう片方でbidding serviceと入札のやりとりができる

デモ

  • kafkaとlagomを使ったメッセージング
    • item serviceでsubscribeして状態が変わったらその情報をbidding serviceへ流す
  • billing serviceが死んでも現在価格は閲覧できる

まとめ

  • モノリスをマイクロサービスにリプレイスするにはデータフローの再設計が必要
    • 単にサービスを分割するだけではいけない
    • 抜本的な作り変えが必要
  • 障害と一貫性のくずれは管理する必要がある
    • そのために4つのパターンを紹介した
      • circuit breakers
      • failure degradation
      • asynchronous messaging
      • denormalizatoin

see more