ミニサービスアーキテクチャでハードモードな現実を乗り越え……たい by moomooya
Microservices Meetupで初めて登壇してきました。
サービス立ち上げ時にマイクロサービスでイメージするサービス分割単位(機能単位)だと分割難易度が高すぎるから、もっと大きな単位(業務単位)でのミニサービスアーキテクチャの適用を考えています、という話。
「『マイクロサービスアーキテクチャ』ではサービス立ち上げはモノリシックで
と書かれているが、そんなのマイクロサービスアーキテクチャとかドメインの概念に精通したハイスキルエンジニアで固めないとごちゃごちゃになって分割できなくなるのが目に見えているじゃないか」という前提での検討。
近い内に独立した記事で書こうと思います。
Microservices 時代の開発環境 by mtsmfmさん
quipper
スタディサプリ
複数アプリDB共有 a.k.a. 分断されたモノリス
本番となるべく同じ環境でらくちんしたい
本番と開発で異なる
- 開発docker-composer
- 本番k8s
Draft より Helm がつらそう
yamlをテンプレートで組むのが辛い
DraftはHelmをラップしたようなツール
Kustomize: yamlとyamlをマージするようなツール
実行コマンドの結果をsecretにしたりもできる
本番に欲しいものと、開発環境でだけ欲しいものを分けておいてガッチャンコできる
DraftにあってKustomizeにないもの
Kustomizeはマージに注力しているためk8sに展開する楽な方法がない
sedで十分という結論に
個人ごとに違うSecretsを.env的に1ファイルにしたい
開発用S3にアクセスするとか
PR前に動作確認用のDocker imageのビルドはどこでやればいいのかわからん
新規サービス立ち上げでマイクロサービスを考えてみる by Spring_MT
(前の発表を受けて)
ローカルでの動作担保はSwaggerの定義ファイルでAPIの動作を担保
新規事業の立ち上げのときはどうするべき?
- 最初はモノリシックで作るべきと言われている
- 分散モノリスは最悪
- 早いサイクルを求められる
マイクロサービスにしたいとき
- デプロイを容易に
これで分けてしまうとマイクロサービスっぽいものになってしまう、つらい
境界づけられたコンテキストで分割
この単位であれば技術アーキテクチャで分割できる
トランザクションの結合は強力
境界づけられたコンテキストを跨いでトランザクションで結合されている部分は注意
トランザクションの中の処理に注目
トランザクションが分割不可のときはコンテキストは分けられない
ゲームで言うと仮想コインと課金、課金APIで死ぬパターンが多い
ひとかたまりで扱いたいデータを意識する
データベースを分ける
複数DBを扱うことになる
railsはあまり考慮されていない
複数DBを扱えるように octopus を使っている
共通系統とユーザー系統でDBを分ける
跨いだ処理を書こうとしたときになにかおかしいと気づける
(帰り道で話した話)
- ゲームで機能面からみてしまうと課金API、ゲーム内通貨APIを分割しがち
- 課金とゲーム内通貨に結果整合性は許されないので、こういう分割は間違っていた
- サービス分割はユーザー要件に合わせないとダメ
SSRに立てたnodeサーバーを認証機能を追加してBFFに転身させた話 by daiki_miuraさん
クライアントとサーバーの2系統から認証APIを叩くことになった
-
案1
- SSRのときはセッション情報をredisに置く
- CSRのときはlocalStorageに保持
-
案2
- NodeサーバーでBFFつくる
認証用のエンドポイントを作った
今後BFFとして育てていきたい
マイクロサービス縦に割るか横に割るか by nabnab1さん
もしもfacebookが巨大なモノリスだったら
今の職場でゼロから設計したらどうやるか
- backend 1 : frontend 1
- backend N : frontend 1
- backend N : frontend N
- サービス単位で分割
- モノリシック
サービス単位で分割=縦で割る
N : N =横で割る
デプロイおじさんのお葬式 by kenjiszkさん
デプロイが面倒だったから「デプロイおじさん」アプリを作った
ついに「デプロイおじさん」を使わなくなったのでお葬式をしたい
マイクロサービスにデプロイ
- 各サービスは好きなときにデプロイしたい
- いろんな言語のアプリケーションがデプロイされる
- デプロイ設定はどこに?
- docker前提
①ローカルPCからCapistrano
- 気の迷い
②Circle CIからのCapistrano
- ちょっと違うけど同じような設定が各サービスに入っていた
③deployojisanからのCapistrano
- デプロイ機能も1つのサービスに
④dockerによるdeployojisanへの引導
- スケールしやすさ
⑤新たなオジサンJenkins
- なぜ今Jenkins
- ただで使えるサーバーがあったのでCircleCIのコストダウンのため
- JenkinsfileとDokcerfileがあればいい、ようにしたい
あらたな問題
- githubのAPI limit
- Jenkinsの管理はつらい
今後の展望
- デプロイシステムはマイクロサービスとして持つのが良さそう
- deployojisanのお葬式は脱属人化
Microservices のお陰でECS移行が大変だった話 by kubochinさん
5つのサービスをEC2からECSに移行した
EC2の問題
- スケールしにくい
- 余剰リソース
Microservicesに感じたこと
サービス多すぎ
- 現在58個 インフラの移行が大変
- インパクトが小さいサービスから移行可能
- 失敗してもインパクトが小さい
CSS事件
- CSSを壊してしまったが1部だけですんだ
環境変数が多すぎる
- 301個の環境変数を用意した
- Administokenを作った
- 環境変数の設定が大変
- 多いと管理できない
マイクロサービスのCache戦略 by kosakoさん
Retty
- PHPでモノリシック(数GB)
- 7年もののレガシーコード
- アプリAPIなどを切り出したりした
- 分断されたモノリス
これからきれいにmicroservices化していく
Cache戦略
- 効率的
サービス要件に適している
ログインして常に最新情報がほしいときは向かない
Cacheのタイプ
- TTL
- 一定の時間キャッシュする
- 更新に時差がある
- 一貫性
- DB Cacheのようなデータ
- 更新時にクリアすれば実現できる
TTLタイプ
- 複数階層でキャッシュされると更新時期のコントロールができなくなる
- 設定ミスでキャッシュが消えないとか
キャッシュ境界
- CDN
- API Gateway - Microservices
- DBに一番近いMicroservices
API Gateway Cache
- パフォーマンスに問題なければしなくていい
- 2パターンありそう
- アグリゲーションの前と後
まとめ
- サービス要件が大事
- 現在と未来を見越す
- API Gateway Cacheはやりやすそうだけど注意深く
質問
クライアント側のキャッシュ戦略は?
- アプリだと自由に制御できるので積極的に使ってた
- ブラウザはまだ検討中
TTLは相手のドメイン要件にもよるけど、呼び元が決めてしまうのはあり?
- ありだと思っている
- サービス要件の複雑化を招くかもしれない
- 呼び元が勝手に決めれない場合もあるかも
- ゲームとかなら使わないことが多い
- キャッシュもバージョニング必要
マイクロサービスの分析基盤 by kommyさん
分析基盤への要求
- 散ってるデータをとにかく集める
- データが参照しやすいこと
FiNCの分析基盤
- データを集める
- DBのデータDMS
- クライアントのデータFirehorse
データ加工する
- BIツールの前にデータを加工する
- BIツールのクエリは地獄のように重い
- redshiftでもつらい
S3めっちゃ便利
- Redshiftへのデータ出し入れが簡単かつ高速
- Redshiftよりも容量あたりが安い
直接Redshiftを参照しない
- どんなに努力してもRedshiftが不安定がことがある
- S3にデータを置いて参照系から見に行く
マイクロサービスだからこそ分析基盤が大事
- データは分析基盤からしか見れない
- データを見ながら意思決定をする
- 分析基盤がないと意思決定ができない
質問
- ユーザごとのトレースの仕方
- ユーザIDがあるのでIDで
マイクロサービス化によってクライアントが受けた恩恵 by nankitiさん
クライアント(Android)はどんな恩恵を受けるのか?
- 単一障害点の解消
- 複数サービスの統合
- データ構造の差異
単一障害点の解消
- 一部が落ちても全部が落ちることはなくなった
- でもアプリケーション全体として処理が進まないから……
複数サービスの統合
- 非同期でサービスを叩いてUIに統合したい
- Androidは非同期処理が難しい
データ構造の差異
- JSONの構造が違う
- ほんとつらい
- パースするDTOが複数必要
腐敗防止層の設置
- DDDの文脈で語られることが多い
- システム間のモデルの侵食をふせぐ
- しかしクライアントからサーバーのモデルは参照してしまう
クライアント側で変わったこと
- GraphQLへの変換層を置く
- 必要なパラメータを型付で取れる
結論
- クライアントとのすり合わせが必要
- 特に以下
- 複数サービスの統合
- データ構造の差異
質問
- BFFはどちらが受け持ち?
- もともとGraphQLでバックエンドが書いている
- フロントエンドで専用APIを実装するように切り替えている
- 今はNodeだが、Kotlinにしてフロントエンドに移す計画
Building Microservices (Sam Newman) の読書会をしたら最高だった話 by qsonaさん
- 2015年にはマイクロサービス指向ですすめていた
認識のちがい
- 推進派と懐疑派
共通認識が広まった……
マイクロサービスにおける結果整合性との戦い by ota42yさん
結果整合性
- 途中では整合性が崩れるが、十分な時間が過ぎれば最終的には整合性が取れる
- BASE特性として語られる
- ACID特性との比較
イベントドリブンアーキテクチャ
- サービス間をイベントの投稿購読で疎結合につなぐ
結果整合性の担保
他のサービスへの送信が失敗した場合
- リトライするべきかしないべきか
- 処理済みだけどレスポンスでタイムアウト
- 送り手側がリトライするのは無理
- 受け手側で何度送信されても大丈夫に作る
- 防御的プログラミング
- 冪等性
冪等性
- append(1)は冪等ではない
- set(1)は冪等である
これだけでは解決しない
- 同じことをしたい場合
- ユニークなキーを入れるのもおかしい
- トランザクションの外で投稿する場合に、投稿だけリトライしたいことがある
- 芋づる式にイベントが起きるので、冪等性を担保していないサービスが1つあると連鎖が起きてしまう
解決策
- 冪等性のキーを持って、トランザクションのキーとする(≠イベントのキー)
- 2回目のトランザクションではキー重複でロールバックされて(何もせずに)イベント投稿が起きる
まだ問題がある
- 実行履歴がDBに保存される
- まだ整合性が担保されていない
- 非同期処理の順序問題
- 受け手が結果整合性を満たせない場合
- サーバー超えたトランザクション維持したいときもあるよね