RailsDM 2019でマイクロサービスについての登壇をしました
だいぶ時間が空きましたが、2019/03/22-23で行われたRails Developers Meetup 2019にて、「我々はマイクロサービスとどう向き合うべきか」という発表を行いました。
言いたいこととしてはほぼスライドどおりで、だいたい以下の内容になります。
- マイクロサービスは麻薬
- 適切に使えば嬉しい
- 嬉しすぎてついつい適切以上に使ってしまう
- 適切以上なマイクロサービスは辛い
- マイクロサービスは問題をより難しくする
- 例えば分割の失敗
- 別サービスを対象にしたリファクタリングは難しい
- モノリシックならまだリファクタリングができる
- どれくらいが適切かは組織の能力による
- 小規模でマイクロサービスはオーバーヘッドが多い
- テクノロジーの進化で中規模でもマイクロサービスがやれるようになってる
- 組織のパワーが上がるとマイクロサービスが大きくても大丈夫
- Railsはマイクロサービスでも十分便利
- マイクロにしすぎないレベルで抑えるのが良い
- 中規模ぐらいならRailsの主戦場
- マイクロサービスよりまずはビジネスの成功を
- サービスをいかに増やさないかが大事
- 全く増やさないとそれはそれでつらい
- マイクロサービスの良さを取りつつ、サービスを増やしすぎない位置を狙う
スライドはこちらです
資料作成時のメモ
このプレゼンを作るうえでまとめたまとめを置いときます。 全部細かい粒度で話すと何時間あっても足りないのでかなり大きく削っています。 なお、時系列的には上の方が新しいですが、入れ替えたりしてるので厳密では無いです。
もしこのトピックについて詳しく知りたいみたいな人がいれば詳しく話すことがある…かも⊂(・8・)⊃
ランキングマイクロサービス
障害の連鎖
マイクロサービス
ライフログとAppの共依存
一気にマイクロサービスにするのは無理
徐々に育てていくのが現実的
すると複雑なマイクロサービスになる
モノリシックでは起きにくいところ
サービス間通信とメソッド呼び出しは雲泥の差
並列数を上げればサーバのボトルネックはなくなる
実際はDBがボトルネックになるので、似た問題は起きる
↓ボツ
マイクロサービスの未来の話
今日のbestは明日のbetterかも
ただし、トランザクション境界や複雑性とかは解決しないので、そっち方面での限界はありそう
いきなりマイクロサービスをやるのはヤバイ
特にスタートアップとか
マイクロサービスにしないと、影響範囲が増えて成長するとやばい
言い換えれば、成長するまでは恩恵は少ない
成功してない段階ではRailsはとても良い
開発が凄い早い
おそらくPMFを最速で作れる
うちの場合
実は結構事業が成功してないころも投資パワーで回せたのでマイクロサービスできたのでは
徹底的にFaaSに振ってしまうのもありかも
とりあえず実装用のサービスを作ると良いかも
マイクロサービスを回すチームが作れない規模
既存のモノリシックが辛い時
第二のモノリシック(でも多少まともなやつ)を作る
先送りだが、マイクロサービスを意識して剥がしやすくする
分断されたモノリスよりかはきれいなモノリスの方がまし
プロジェクト型はむしろ作りまくるのも手かも
優先度が育てる<作る場合
多産多死
ベース+それを活用するサービス達
死んだプロジェクトが生きてる部分に影響させないように
ほぼメンテされてないが、生きてるプロジェクトに一部がいるので足かせになってる
------------------------------
例えば横断的関心事が複雑
クオリティの統一や、セキュリティ的な面がチーム毎でバラバラになる
5.2が出たのにRalis 4.2.1がいたりとか
ruby 2.3.1のまま何年も放置されたりとか
温度感もチームによって違う
チーム毎の優先度を組み替える交渉
チーム外からだととても手を出しにくい
上げるのは外からでも出来るが、QAを考えるとオーナーとの交渉が必要
チーム<サービス数なので、人のリソースが足りない
機能追加はしなくても問題ないけどセキュリティはせざるを得ない
試した対策
gemの一覧を表示できるサービス作ったり
https://github.com/ota42y/gemicoma
マイクロサービス毎の進捗シート作ったり
隙間時間で機能改善をやるムーブメントを作ったり
規模が小さいので個々の問題は簡単だが、量が多いのでカバーが難しい
モノリシックなシステムだとgemのアップデートとか大変だけど、みんなが注目するのでカバーは楽
十分な人員がいれば問題はない
すべてのマイクロサービスに中堅エンジニアがそこそこ関わってる…的な状態を作れれば良さそう
たくさん作って手をかけられない部分がいくつか出るか、少なくして難易度を上げるかどっちかのトレードオフ?
どれくらいやるかのグラデーション
サービス毎のドメインは明確になった
事業部レベルの分割
App/EC/BtoBで分けてる
やっている事業が全く違い、コードベースも違う
アカウントは共有している
ビジネス毎に何処でやるべきかは明確に分けられた
アプリチーム内の分割
メディア/lifelog/コミュニティ/オンボ
マイクロサービス毎にやるべき事が明確に別れるようになった
コミュニケーションコストが上がる
APIの数がとても多くなる
クライアントだけでなく他のマイクロサービスからも呼ばれる
複数の要素をまとめて返すようなAPIは作れない場合がある
マイクロサービスを超えるような場合
歩数のタブのランキングとか
問題
APIをたくさん作る際のコスト
仕様を決めて繋ぎこんで微妙に型が違う…みたいなの
既存のAPIを使いたくてもドキュメントが無いと実装を読み込まないといけない
マイクロサービスごとに音楽性が違う
クライアントは結合しているので、マイクロサービスごとに処理を頑張る必要性がある
複数呼び出しのコスト
必要な情報を持ってるマイクロサービスに個別に問い合わせる必要がある
モバイル環境だと通信回数のコストは大きい(HTTP1)
データの整合性
試した対策
サービス間のAPIコールを楽に実装できるようにする
OpenAPI
client library生成
gRPC(使ってない)
APIがドキュメント通りのインタフェースを持つことを保証できる
クライアントから見たときのマイクロサービスを楽にする
複数呼び出しのコスト削減
GraphQL
BFF
APIコールをしない
イベントドリブンアーキテクチャ
イベントが起きると付随する処理が行われる
AWS SNS + SQS
Kinesis
ストリーミングで常に流す状態
マイクロサービス、良いところも辛いところもある
マイクロサービス単体の開発は確実に楽になる
アーキテクチャが複雑なのでその分のオーバヘッドはかなりある
アーキテクチャの良さは容易に潰れる
個々に独立して動くのがマイクロサービスの利点
独立に動けなくなるとむしろ足かせになる
人数が少ないと兼任が多くなる
リソースの取り合い
コミュニケーションコストの増加
全体的なクオリティの低下
マイクロサービスの利点と欠点はトレードオフ
テクノロジーで解決できる部分はありつつも…
横断的関心事に対処するというのもコストがかかる
真にゼロにはならない
モノリシックの辛いところは解消するが、モノリシックなら辛くないところが辛くなる
うまく良いところだけ取り出せないか
マイクロサービスの良いところを最大限取り出したい
以下の2点が重要っぽい
いかにマイクロサービスを適切なタイミングで切り出すか
マイクロサービスにおける複雑性をどう抑えるか
コミュニケーションとか
インフラとか
いろんなレイヤの複雑性
マイクロサービスにおける複雑性をどう抑えるか
あらゆる複雑性が襲いかかってくる
権限が移譲された適切な組織構造
マイクロサービスのインフラレイヤー
データの整合性
タイムアウトによるデータ異常
どう対処するか
組織構造
良い答えを持ってない
適切に分権してても容易に無視される
人手が足りない+マイクロサービスを増やすとどうしようもない
がんばる
マイクロサービスのインフラレイヤー
いろんな種類のサーバの面倒を見る必要がある
一部が落ちると障害が連鎖して死ぬ
対策は最近出始めている
k8s
Envoy
Ballerina
プラットフォーム側でのサポートもあり、ここは楽になりつつある
`暗黙知が暗黙知のまま放置されやすい`
-------------------------------------------
やっぱボツ↓
ユーザ体感の統一も難しい
デザイナーは共通チームにすることで問題を回避
デザイナーチームはモノリシック
機能毎に別々のチームが作るので…
サービス連携が複雑
連携せざるを得ない部分はある
完全に独立してたら1個のアプリでは無いので…
チームをまたがった作業はオーバーヘッドがかかる
コミュニケーションコストは基本的に高い
APIによる連携は分割されたモジュールを呼び出すより大変
適切な仕様のコミュニケーション、シリアライズ・デシリアライズ、通信異常
別のチームは別の優先度で動いているので
モノリシックより工数調整が大変
プロジェクトの見積もりムズイ
いかにチームやマイクロサービスを超えた機能開発を抑えるかが重要
とはいえプロジェクト型開発は避けられない
チームを超えて機能開発が起きる
コミュニティ+チャット+ランキング
チャット+ミッション+AI
チームによる優先度と、横串の優先度との板挟み
そもそも人が足りなくて1人で複数のマイクロサービスを見てたりする
マイクロサービスを触れる人のリソースの取り合い
キャッチアップもムズイ
暗黙知が暗黙知のまま放置されやすい
アーキテクチャは無形のシステム
マイクロサービスの全体像を把握するのは難しい
誰が何処にアクセスしているか
StreamingArchitectureの導入みたいな、チームの温度感と違う問題も起きる
------------------------------
マイクロサービスの良いところ、悪いところを話す感じ
良いところ
最適な技術スタックを扱える
DeepLearning
速度が必要な時
個々のサービスが小さくなる
コード変更の影響範囲が限られる
見通しやすく、新しい人のキャッチアップなども楽
ここを見てやろうとすると失敗するのではという気持ち
PDCA回す速度早い
たぶん一番重要なのはこれ、ほかはコレを実現するための要素
devops
小さいチームのコントロール下における
意思決定を小さいチームで行える
(適切に権限が割り振られていれば)
逆にどこに渡すかが明確でないと大変では
チーム外の人が実装しようとして、この機能何処に実装すべきですか?という話が出てくる
悪いところ
分散システムの複雑性
サービスを超えたデータの整合性どうするのか
サービス間の依存関係
コードからは読み解きにくいので厄介
サーバレスとかが間に挟まるとカオス
マイクロサービスを超えた作業のオーバヘッド
別のマイクロサービスの作業をするのは大変
クオリティの統一や、セキュリティ的な面でほかチームへ影響を及ぼすのが難しい
StreamingArchitectureの導入みたいな、チームの温度感と違う問題も起きる
結合部分のつらみ
クライアントアプリケーションはマイクロサービス関係ない
ユーザが見る場所では結合が必要
対策があるが…
アプリ分割
モジュール化
マイクロフロントエンド
UXの統一という意味では対策は無い
一番マイクロサービスやってるAWSのコンソール…
デザイン的なあれこれを統一しようという動きはある
辛いところ
通信が複雑
サービス間通信
OpenAPI
GraphQL
gRPC
対クライアント
マルチリクエスト
BFF
Micro Frontend
データの同期
イベントドリブン
ストリーミング
ESB
データの状態が複雑
トランザクションという武器を手放す
人類が手に入れた並列性と戦う武器
Sageパターン
分散トランザクション
結果整合性
冪等性
サービス分割が複雑
権限管理
人に紐づくもの
followとか
roleに紐付くもの
管理画面
サービスをまたいだ処理
横断的関心事
コミュニケーションコスト
ロギング
DDD
分断されたモノリス
どう分割するか
チームが複雑
プロジェクト型とプロダクト型
原義のマイクロサービスは`チームに自由度と責任を与え、自己組織化されたチームに成長させる`のが大事
中心に作っているプロダクトがあるプロダクト型
プロジェクト型も一応ある
某会社とか
ただし、それにそった開発プロセスになってないと
うちはプロジェクト型なのにプロダクト型にしようとしたのが失敗では
とはいえ、オンボチームとかは成功してる
フォーカスすることがぶれない&コントロール下にあるってのが重要っぽい
lifelogチームはプロダクト型チームだけどプロジェクト型の都合で壊滅した。ただ、これはむしろ例外ケースみたいな感じ?
コンウェイの法則
インフラが複雑
Ballerina
ロギング
k8s
datalake
カオスエンジニアリング
障害の連鎖が起きやすく、わかりにくい
未整理
CDCテスト
コンテナのちからがマイクロサービスを推し進めている
複数の種類のアプリケーションの面倒を見るインフラコストが下がっている
生産性を下げない/上げるためのマイクロサービス
生産性が下がるなら、マイクロサービスからモノリスに戻すのも一つの手
(community)
Martin Fowlerもそう書いている
モノリシックカーネルとハイブリッドカーネル、マイクロカーネル
マイクロカーネルが良かったんだけど、
Rails、現実的な解決策だよねという話
実際、スタートアップが立ち上げからマイクロサービスをやるのは愚か
マイクロサービスによるオーバヘッドは無視できない
マイクロサービスにしないと、コミュニケーションパスが増えて人数が増えるとやばい
RailsでとっととPMF作ろう、その後マイクロサービスにしたら?
うちは事業が成功してないころも投資パワーで回せたのでマイクロサービスできたのでは
チームの人数を一定に保つためのマイクロサービスでは :thinking_face:
2枚のピザ理論
社会を構成する人の単位
小隊・分隊
家族とか
https://ja.wikipedia.org/wiki/ダンバー数
狭い意味でのマイクロサービス(分散システム)はもともとやってるよね
MySQL
Redis
誰もデータ永続化を自分のアプリケーションの中に書いてないし
ドラクエ10(2012)はゲームプロセスとかを分割している
ドラゴンクエストXを支える技術
役割に応じて開発するのを分けるというのは、わりと普通の考え方
今の広い意味でのマイクロサービスと何が違うのか
故障要求とかかなー
気軽さが上がったとかもありそう
ecs/k8sが無い時代と今とだと違う
理想的なマイクロサービスとの付き合い方
増やしすぎない
増やす圧力はとても強い
既存のモノリシックが辛ければ辛いほど
完全に別チーム作れるなら話は別っぽい
リファクタリングの方がはるかに楽
既存から切り出す
失敗しにくい(lifelog)
新たに立てるとうーんみたいな事がある
ただし、以降は簡単ではない
たくさんの複雑さがある
過渡期なので有効な解決策が無いことが多い
将来的にはより簡単になるかもね
やるなら
ラッパーマイクロサービス
実質Appにいるけど別マイクロサービスが前にいるあれ
BFFに実装したやつ
機能でマイクロは辛い
ある程度のビジネスでマイクロサービスにするべき
FaaSはやめたほうがいい
社内SaaSぐらいの規模にしたほうが成功しそう
課金系のようなバックエンドの共通サービスというのはある
とはいえ、アレも最初は成功していた
それ単体で成長できないのが問題
communityと紐づく
小さすぎてそれ単体で大きくなれない
PDCAの速度を落とさないためのマイクロサービスなので、PDCA回さないならそんなに意味がない…
コストはかかる
マイクロサービスにしたやつの開発コストは下がる
マイクロサービス間の連携のコストはメソッド呼び出しに比べてかなり大きい
チームを適切に分けて権限委譲したり、サービスの分断面を適切にしたり
分割に失敗したときの影響はモノリシックより大きい
組織ー複雑度の図
マイクロサービスは過渡期
ecsとかk8sが無い数年前は相当大きくならないとペイしない
今はk8sとかenvoyとか出てるので、中規模ぐらいでもペイすると思う
もっと周辺ツールが進めば小規模でもペイするかもね
(ただし、トランザクション境界や複雑性とかは解決しないので、そっち方面での限界はありそう)
CIはあたりまえに、Dockerは徐々に当たり前になりつつある
マイクロサービスはまだ当たり前ではない
良い資料
https://tech.mercari.com/entry/2018/12/01/200159
code:text
チームの人数を6〜10名程度の少人数に保つ
チームに自由度と責任を与え、自己組織化されたチームに成長させる
開発と運用の両方に責任を持つことで、ソフトウェアサイクル全体からフィードバックを直接受け、改善サイクルを加速できるようにする
質の高いツールや自動化など技術的な改善にも確実に投資する
https://gist.github.com/everpeace/c40b69eff6636b9ec2f9
https://techlife.cookpad.com/entry/2014/09/08/093000
http://kimitok.hateblo.jp/entry/2014/11/09/211820
code:text
めったに変更されないシステムの部分は、現在変更をたくさん行っている部分とは異なるサービスにするべきです。もし2つのサービスを同時に変更することが何度もあれば、それはそれらのサービスを1つにすべきサインです。
TDのマイクロサービス化の手順が良かった
資料どこだっけな…