Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Microservices Architectureを超大規模プロジェクトでやってみた

Microservices Architectureを超大規模プロジェクトでやってみた

Yasuhiro Miyake

November 18, 2016
Tweet

Other Decks in Programming

Transcript

  1. Microservices Architecture

    超大規模プロジェクトでやってみた
    - 一筋縄でいかない苦闘の一年間 -
    株式会社ワークスアプリケーションズ
    三宅 泰裕

    View Slide

  2. Agenda
    ● HUEの変遷
    ● Dependency戦国時代
    ● MSA黎明期
    ● MSAなう
    ● まとめ
    ● Q & A

    View Slide

  3. 0. HUEって?

    View Slide

  4. HUE
    ● ふえ?
    – High Usability Enterprise application
    – 「ひゅー」と読みます
    – 電球ではありません。。。
    http://www.worksap.co.jp/hue/ 

    View Slide

  5. HUEの特徴
    ● Cloud Native
    ● 分散処理機構
    – 膨大な量の帳票の集計の高速化 (一億明細とか)
    ● 人工知能
    – 学習に基づく、Input Less化
    ● 応答速度にコミット
    – 100msで応答するという挑戦

    View Slide

  6. 規模感
    ● 開発者
    – 3000+ (日本、上海、シンガポール、インド)
    ● CIチーム
    – 30名(日本、上海)
    ● 運用チーム
    – 15名(増員中)
    ● 偉い人
    – 一杯

    View Slide

  7. 今日、言いたいこと
    ● MSAへの移行は難しい、けど出来る!
    – 技術的な難しさ
    ● 言うても組み合わせ、実はそんなに新奇性はない
    – 精神的な難しさ
    ● 「諦める事」への慣れ
    ● 「仕様」という言葉の魔法感
    – ノーガードになる
    ● パラダイムシフトを許容出来ない
    – 目に見える範囲で「改善」を積み上げる
    Springそのものの話は、あんまり無いですね、今回...

    View Slide

  8. 1. HUEの変遷

    View Slide

  9. プロジェクト開始当初
    ● Springエコシステムをある程度使う
    – 2年半ぐらい前の話
    Spring MVC
    Spring JDBC Spring Cache Abstraction
    Application Code
    Forneus (自作超高速レンダリングエンジン)
    Google Closure Library

    View Slide

  10. え?なんでRDBMSつかってるの?
    ● 大号令、「RDBMSから脱却!」
    – 2年前ぐらい
    ● Cassandraの導入が決定
    ● Sparkをバッチ処理にもってくる
    ● メイン処理からRDBMSは完全撤廃
    Spring MVC
    Spring Cache Abstraction
    Application Code
    Forneus (自作超高速レンダリングエンジン)
    Google Closure Library
    KVA (C*ドライバ)

    View Slide

  11. ねえ、バージョンアップしてみて?
    ● 1年ちょっと前
    – 状況
    ● 三週間あればバージョンアップ出来ます!
    これって。。。

    View Slide

  12. Monolithic !!

    View Slide

  13. 苦闘の歴史の始まり
    ● 巨大でモノリシックなモジュール
    – 膨大なソースコードをマージして1つに
    ● ビルド時間
    – ほぼ1日(14時間)
    ● 環境構築の時間は含まれておらず、構成確認は出来ない
    ● テストも流せない……
    ● 浪費癖
    – .warを動かすには、32Gbyteのメモリが必要です!!
    ● 進まない理解
    – MSA、え?それって美味しいの??

    View Slide

  14. 正しく考えてみる:仮説
    個別のサービス単位でバージョンアップする
    他に影響は及ぼさず、高速にビルド・デプロイ
    サービスレベルでの依存の排除
    WebAPIにのみ依存する開発スタイル
    ということは?

    View Slide

  15. Micro Services Architecture !!
    ● これなんじゃね?

    View Slide

  16. HUEの制約
    ● 目的
    – 100msでの応答速度を達成する
    – 統一感のある、UI・UX
    ● 戦略
    – コンパイルの出来るJS
    ● Closure Compiler → Google Closure Library
    – 一元配信出来るCSS
    ● LESS
    – サーバサイドレンダリング
    ● Forneus

    View Slide

  17. HUEの要求(一部)
    ● ビジネスドメイン単位で導入したい
    – 例:) お客様が購入されたライセンス単位で
    ● 品質を担保したい
    – 100msでの応答速度
    ● フレキシブルなスケールアウト・スケールアップ
    – 理にかなった、UI / UX
    ● 導入作業を軽減したい
    – ERPの導入作業は凄く大変…
    ● 時間、リソース、複雑さ

    View Slide

  18. 2. Dependency戦国時代

    View Slide

  19. 事実を詳らかにしていく作業
    ● とりあえず孤軍奮闘
    ● まずは依存性の調査
    – mvn dependency:tree
    – Dependency Analyzer
    – JSレベルでも、deps.jsとかを眺めてみる

    View Slide

  20. こうなった。。。

    View Slide

  21. どうしよう。。。
    ● 選択肢は2つ
    – 新しいものは美しく
    – 既存のものはサヨウナラ
    ● 分けると良さそうな気がする
    – 最早、管理できない単位なのは明白

    View Slide

  22. レポジトリ分割闘争
    ● 分割するってことは
    – 管理する単位自体を変えるっていうこと
    ● どっちがいいの?
    – 1レポジトリで全部やるか
    ● ツリーは1つ
    ● レポジトリも1つ
    – 細かく分けていくか
    ● ツリーは1つ
    ● レポジトリはN個

    View Slide

  23. 1レポジトリ派
    ● Pros
    – インテグレーションレベルでの問題発見の早さ
    ● 製品の弱点がすぐに分かる仕組みをつくりやすい
    ● Cons
    – Cloneの速度
    ● 単純な物量
    – テスト時間
    ● ユニットテストすら工夫して流す必要
    – ビルド・デプロイ時間
    ● Googleスタイル、彼らはビルドツール開発にも注力
    – Bazel → https://bazel.build/

    View Slide

  24. レポジトリ分割派
    ● Pros
    – cloneが速い
    – ビルドも早い
    – テストもしやすい
    ● Cons
    – インテグレーションレベルでの問題は発見しづらい
    ● ここに対する処方箋は必要

    View Slide

  25. HUEの戦略
    ● Jenkinsレベルでどんどんテストを組み込む
    – 1レポジトリに組み込まれるもの
    ● Pre-merge build (Merge前にUnitTestは流す)
    ● Smoke Test (Dockerベースで起動確認だけする)
    ● GitlabでのReview Board (シニアのLGTM必要)
    ● 開発者を不用意に待たせない
    – 2000人を10時間も待たせられない…
    ● インテグレーションレベルの問題
    – 0から環境を毎日作ってそこでテスト
    ● ビルドこけたら緊急出動!
    – Immutable Infrastructureを目指す

    View Slide

  26. 戦略が決まったので、実行
    ● 「意味ある単位」に分解
    – 業務機能での何となくの塊(完璧でなくていい)
    – 共通機能と業務機能は絶対に別
    ● ここは理解が得られやすい
    FW
    (全部入り)
    認証
    経費管理
    残り
    イテレーション単位で狙いを定めて、分解していく

    View Slide

  27. 得られた知見
    ● 共通部分は以外と切り出せる
    – 機能的な重複は意外と少なかった
    – ソースはカオスでも一旦置いておける
    ● Refactoringは独立宣言後でも大丈夫(優先度的に)
    – 切り出せたものは極小に
    ● 32G → 650Mbyte
    ● 業務アプリはやっぱりFWにべったり
    – やったところでスリムにならない
    – メモリ:32G → 24Gぐらい(激重)
    要はやっぱり、「依存関係」

    View Slide

  28. 3. MSA黎明期

    View Slide

  29. 作戦を立て直す #1
    ● レポジトリを分割してしまえは正しい
    ● メモリ圧迫の原因は、Beanの過剰生成も
    – 去年の発表参照
    ● 共通部分の分離が急務だが、影響範囲は莫大
    – 可視化しないと、どうなっているか分からない
    ● ドメインの分割も出来ていない
    – 実は、大きなレイヤでは分かれている、ERPだから
    ● HR, AC, SCM
    ● 要するに、ヒト・モノ・カネ

    View Slide

  30. 作戦を立て直す #2
    ● FWに入っているものにも何か混ざってる
    – 承認ワークフロー
    – Collaboration Features
    ● Spreadsheet, Timeline, Drive, Talk etc...
    ● 製品を構成する要素としてはFWに見えるけど
    – 実は、サービスとして切りだされるもの
    ● 例:) Spreadsheetは、Google SpreadsheetのERP版

    View Slide

  31. Beanの生成は手動定義
    ● Auto Confguration的ではなく
    – Confgurationクラスに必要なものを自分で書く
    – 依存ツリーは自分で意識して、@Importする
    @GuardedConfiguration(ExampleConfig.class)
    @Import({CassandraConfig.class})
    public class ExampleConfig {
    @Bean
    public Foo foo() {
    return new FooImpl(bar());
    }
    @Bean
    public Bar bar() {
    return new BarImpl();
    }
    @Bean
    @Autowired
    public Baz baz(KeyValueAccess kva) {
    return new BazImpl(kva);
    }
    }
    @GuardedConfigurationはご愛嬌

    View Slide

  32. Gitレポジトリは分割する
    ● FWと称して全てを内包していたので
    – どんどん分解
    Timeline
    Approval Spreadsheet
    Framework

    View Slide

  33. 普通の景色に戻す(ように頑張る)
    ● ApplicationとLibrary
    – Library: 内製のラッパや、ユーテリティ、共通機能
    – Application: サービスそのもの
    ● Application間はWebAPIでやりとり
    Application A
    use
    Logging Encryption Spring Boot
    use use
    Application B
    Application C
    WebAPI
    WebAPI

    View Slide

  34. ビルドの単位も切り離そう
    ● ドメインが分割不可能なら
    – 大きな開発組織単位で
    ● Stakeholderが減る
    – 開発のやることは増えるが、責任は明確に
    ● 出来るだけ政治的混乱に開発は巻き込まない
    Framework Collaboration
    Human
    Resource
    Accounting I/F

    View Slide

  35. デプロイは一括でしか出来ない
    ● ドメインの分割は本質的な問題
    – 下記の状態。双方に初期出荷データが必要になる
    ● 理想解
    – サービス間でデータの共有をしない
    ● 検索Indexどうするの?
    ● データの分割はとてつもなく難しい
    – 定義の曖昧さ、責任の曖昧さ
    ● 例) 承認ワークフローって皆、使うけど誰のもの?
    ● 歴史的問題
    – 組織はMSAに都合良く組織されない
    F/W Accounting

    View Slide

  36. 得られた知見
    ● ここまでやると、そろそろ本質に気づいてくる
    – ドメインとは
    ● 実は、売りたい単位?
    ● 実は、バージョンアップしたい単位?
    ● 実は、ライセンスの単位?
    – こんな議論が繰り広げられるようになる
    ● で、更なる(現実めいた)オーダが飛んでくる

    View Slide

  37. 4. MSAなう

    View Slide

  38. で、幾らかかるんだっけ?
    ● メモリを大量に消費する作りで
    ● インスタンス自体はバラバラになっていって
    – あまり、メモリ自体の削減効率は上がらず......
    ● ビルドは綺麗になったものの
    ● デプロイは1回のみ

    View Slide

  39. View Slide

  40. コストをさげるんだー!!
    ● インスタンスコスト
    – 利用時間あたり、どれぐらい稼働させ続けるのか?
    ● HUEは、1インスタンス、1サービスだと無理がある
    ● Kubernetes
    – 巨大インスタンス1つで、N個のPOD(サービス)という戦略が可能
    ● かつ、M/Wリソースは共有出来ないといけない
    – 各社毎にインスタンスを立てていくと、凄く高い
    ● Multi-tenancyという選択肢
    ● Managed Serviceも活用しよう
    – AWS Lambdaとか
    ● 100ms単位課金(使った分だけお金を払う)

    View Slide

  41. 余談ですけど、高いですよ!!
    ● 冗長性
    – だって、普通に落ちるからね
    – 昼間はN個、夜間はN/2個とかは必要です
    – Multi-AZとかMulti-Region考慮すると余計高い
    ● というわけで、下記は必須です
    – 出納大臣(もしくは、Billing API)
    – 性能大臣 (もしくは、負荷試験と綿密なCP)
    コストと性能はトレードオフ、しかし、妥協点は見出すべきです!!

    View Slide

  42. じゃあ、こうしよう! (取組中)
    ● APサーバも含めて、M/Wは、Multi-tenancy
    ● Multi-regionも視野にいれる
    AP C* ES
    Kafka
    Redis
    Managed Service
    AWS Lambda とか...
    VPC

    View Slide

  43. War → Docker (取組中)
    ● ライブラリの制約からの解放
    – やっと、Spring Boot使える...
    ● Docker Fileを成果物にする
    – Buildまで開発チームで責任もってもらう

    View Slide

  44. 運用も委譲しちゃえ (取組中)
    ● ビルド
    – 開発者がやるもの
    ● デプロイ
    – Ansibleベースで環境構築スクリプトも書いてもらう
    ● Scaling Factorとか、非機能要件
    – 負荷試験環境でCPして、決める
    – k8sベースなので、YAMLで決められる
    ● モニタリング
    – 可視化ツールで頑張る
    ● Prometheusとか使い出す

    View Slide

  45. CIの役割は?
    ● インテグレーションの専門部隊へ
    – Jenkinsで魔法かけない
    ● Monolithicアプリは往々にして、魔法で出来ている
    ● インテグレーションレベルでの問題解決を!
    – MS単位でリグレッションテスト
    – MS間で結合テスト
    – データの適用テスト、SlowTest等
    ● 開発クオリティを担保する方向へ!!
    – ビルド屋さんからの卒業
    ● 開発ライフサイクルそのものを定義していく部隊へ

    View Slide

  46. 本番環境は?
    ● もちろん、専門チームが必要
    – コンプライアンスとかの問題
    ● Opsを担う人を育てねば。。。

    View Slide

  47. 5.まとめ

    View Slide

  48. インフラ #1
    ● インフラドリブンでいこう!
    – 個々の開発者の理想はチグハグ
    ● 正直な所、意志の統一はほとんど不可能に近いかも……
    ● これは揃えとけ...
    – Jenkins的なビルドツール
    – Gitレポジトリ申請フロー
    – 依存性をチェックする機構
    ● マージ前、トピックブランチにpushした直後
    ● どんどん落とす:Failさせる
    ● ビルドドメインを決めたら、そこもチェック対象に

    View Slide

  49. インフラ #2
    ● 構成管理はしっかりと
    – 毎日、環境は作りなおす
    – 当然、スクリプトで管理するべき
    ● Ansibleとかいい感じ
    ● 出来上がった環境もチェックに使う
    – 環境構築スクリプト時点でも問題は発覚する
    ● CI的な役割をする人間もどんどん文句言う
    – 第三者的評価もする
    ● 素朴な疑問に目を背けない
    – 「自分の評価対象だけ、最新に出来ないでしょうか??」

    View Slide

  50. 開発者 #1
    ● まずは、「依存」に目を向けてもらう
    – mvn dependency:tree, 自分たちの依存はしっかり分かっておく
    ● 「依存」と闘うことに、嫌気がさしてきたら
    – Dockerベースでのビルドまでを出来るように頑張る
    ● 当たり前をちゃんとやる
    – ステートレス, ドメインをしっかり定義して、そこを逸脱しない
    ● 何でもテスト出来るようにしておく
    – Dependencyチェック, 初期出荷スクリプトのチェック, 各種テスト
    ● 一番大事なことは
    – 「覚悟」しろ! って言うこと
    ● 「運用」とか言われると、始めは誰しも怖いものです

    View Slide

  51. 開発者 #2
    ● Web APIベースでの開発には...
    – 互換性維持は基本、出来ればForwardも
    ● Unit test、Swagger、バージョンを組み込んだAPIデザイン
    – 低レイテンシ
    ● 非同期、バルク、キャッシュの有効利用
    – 結合テストの効率化
    ● モック、SDKの提供 (Feign的な...)
    – 監視のためのWeb APIのトレーサビリティ
    ● 相関ID (Sleuth的な...)
    – 可用性の確保
    ● サーキットブレーカパターン、インフラも含めて (Hystrix的な...)

    View Slide

  52. 組織
    ● 開発は出来るだけ、Agileで
    – 早く見つけて、早く修正
    ● レビュー機関の必要性
    – 製品としてのコンセプトを判断できるチーム
    – Architectureを判断できるチーム
    ● インフラチームとがっつりタッグを組まないと、形骸化
    する
    ● APIのルール、デザイン
    ● M/Wの使用方法
    – 無駄なコストをかけない
    – デザイン(UI/UX)を判断できるチーム

    View Slide

  53. 苦闘の歴史は?
    ● 巨大でモノリシックなモジュール
    → 6個に分割、Gitレポジトリはもっと細かく
    ● ビルド時間
    – ほぼ1日(14時間) → 5〜40分を「並列」で
    ● 浪費癖
    – Xmx:32Gbyte    →  Xmx:1-4Gbyte
    ● ライ○ップもびっくり
    ● ちなみに、話者も20K減量(前年比)
    ● 進まない理解
    – 無理、無知 --> どうしたら分割できるだろう?

    View Slide

  54. Any Questions?

    View Slide

  55. We are hiring!!

    View Slide