「merpay インフラ Talk #3」の私的イベントメモ

merpay インフラ Talk #3に行ってきましたの私的イベントメモ

# 【概要】

connpassより引用
https://mercari.connpass.com/event/104430/

```
ついにサービスリリースを迎えたメルペイ。
今までなかなかお話できなかったリリースするまでの道のりや金融という事業ドメインならではの苦労など
メルペイでプロダクトを作るのではなく、下回りを支えるメンバーが集合して、どのようなことを考え、何をしているのかについてお話します。

これまでにお話したくてもできなかったことをたくさん公開予定なのでぜひ奮ってご参加ください！
```

そこでの内容をメモった内容をそのままアップしますー。


※ slideは後日共有されるそうです
※ 注意：メモをそのまま載せてるだけなので、誤字脱字があります

# 【スライド】追記
https://mercari.connpass.com/event/104430/presentation/

# 【イベント内容】

## 19:50~	merpaySREがやっていることの紹介 by @tjun

### アーキテクチャ
- マイクロサービスでやってる
- マイクロサービスをやってるのは
	- サービスや組織をスケールさせたいので、それに耐えられるように
	- サービスごtに機能やデータを分離している、DBもチームもコードも全て

### SREのしごと
- Reliabilityに関わること全部やってる
- Mirosevicesのリリース。運用のサポート
- Infra as Codeのレビュ0とか

### Microservice
- 20~30くらいある
- 毎月増えている状態
- SREが各チームのサポートを行う

### チーム
- Architect Team
	- Go/gRPC, Microservices, gateway
- Solution
	- GCP, Spanner
- Microservices platform
	- K8s, Spinnaker
- SRE
	- Mercaiサービス全般
- Security

### 現在と課題
- Toil多い：マイクロ化にける権限の課題
- Microservicesの運用体制も不十分なところが多い
	- リリースするたびにSREのしごと増えてきている...
- Microのテスト、QAをやるの難しい
	- 組み合わせに対するテストどうやってやろうか、問題
- Availability, Security周りはまだｍだやることがいっぱい

→ 自動化見える化、ServiceMeshとかやっていきたい！


## 20:05~	負荷試験について by @kazegusuri

- 安全に出したい！ということで結構↓をちゃんとやってました！のお話

### 計画を立てる
- ユーザー観点で試験内容を決める
	- なぜこんな負荷試験をしたか説明可能、再現可能（次の若干条件を変えてテストをしたいときに活かせるように）にする
		→　決済/金融系は特にシビアなのでちゃんとした証拠を残したかった
	- エンドポイントごとにアクセス数を推定する
		- 今回はユーザーをベースに考えたので、シナリオを想定してそのテストを行った
	- 数値を決めた根拠を残す
		- 次回の試験でも別の人が同じことができるようにする
		- 人によっては数字の根拠が適当だったりするので、いい根拠になる
		- 本番に出して実際の数値が出た後に、振り返ることができる
- すうちもくひょうの決め方
	- キャンペーン時のピーク性能（RPS）
	- SLO
		- レスポンスタイム 99%ileでn秒以下
		- エラー率n%以下
- キャパシティプランニング
	- スケール可能なことも確認する
		- 今後の成長した時に、スケールさせられるか
		- 別に全てをやる必要はない
		- が、限界値を知っておく必要はある
		- どこまでスケールできる？
	- 今後のキャンペーンなどで必要な性能が予測可能に
- ベンチマークコードを設計する
	- ツールを自作した
		- いろんな機能をためそうとすると、事前の条件の準備が色々あって大変だった
		- 面倒だったから作りました
		- OSSのベンチマークのコードをパクって改良した

### 負荷をかける
- 負荷試験にはドメイン知識が必要
	- ブラックボックスでやるの理想だが。。。
	- 特定のユーザーが一日にうん万回も決済する？
	- テストをするのに↑楽な思考によってきてしまう
	- 現実的な起こり得る問題なのかどうかをよく検討すること
	- 起きた問題は「それって本当に異常？」かどうかをよく考える
	- （↑これが難しい）
	- 普通はしないだろ、という動作が本番ではあったりするので後でハマったりする
- 繰り返すことが重要
	- 同じ設定で何度も確認する
	- そのほうがたまたま成功した、みたいなことがなくなる
	- 線形に結果が伸びていく、ということが確認しやすい
	- 今回は短い負荷試験を何回も回した

### 改善する
- カイゼン
	- カイゼンには観測できることが重要
	- = 今なにが問題か
	- カイゼンする時に必要なこととしては、メトリクス取ることと分散トレーシングをすることが大事
	- 試験中にどこに問題があるの？とかわからないと本番でも絶対わからない
	- だから試験中に必ずわかるようにしておくことが大事
	- ログは最終手段として考えておいて、その前に可視化しておくことが大事
	- 問題店の把握
		- 試験して、調査
			- CPU増やす　→　別（I/O）が詰まる　→実装見直す　
			- を繰り返すことが多い
		- Traceをまず見る
			- ひと目でここがおかしい！ということがわかるようになる
			- 例えば、Traeした時に処理が途中で断続して謎の空白ができるなど (計測出来てないだけで処理が動いてる)
- 本番環境でも試験する
	- 可能な限り本番環境でも試験を行う
	- 参照系だけでも！
- 反省と課題
	- 短期間の負荷試験を回すことをしてたが、長時間負荷をかけた時に発生する問題もあった
	- 負荷試験のときでも、4コアしかないのに超負荷かけると不安定になったりする
	- 超高負荷のときにどうやって安定させようか
	- マイクロサービス全体に影響が広がる


## 20:20~	MerpayでのMonitoring: by komattaka

- SLI/SLOが美味いこと動いてきたからその話
- コンセプト
	- DataDogにいろいろなサービスの情報を集約して、一括して見れるようにした
	- ただ、得手不得手がある
	- 例えば、DataDogはApplication Bug Trackingなど
	- その際は Stackdriverを使っている
- Metrics Driven Development
	- Work Metrics : 直接的にコンバージョンに影響があるもの (表示、決済、など)
	- Resource Metrics : ずっとほっとくと↑になるもの (CPU, Memの使用率など)
	- Events : 例えば新しいバージョンへのリリース、キャンペーンを打つなどで新たな↑２つに影響が出るもの
	- 常に見ることが大事！
- SLI/SLO
	- SLI: サービスレベル指標
	- SLO: サービスレベル目標 = SLI + 目標
	- SLA: サービスレベル契約 = SLO + 罰金
	- ↑から作っていく
	- やりがちなのが、全てにアラートつけちゃったりすること
		- SLIで重要なものを決めて通知の嵐をなくした
	- UX / Customer Journeyに基づいて、PMが主となって考えてエンジニアがSLIを割り出して決めるのがいい
	- 一つ一つ要件に対して言葉を分解していく「何がやって」「正常なものは」「どこで図れる？」「何秒まで許容できる？」
		→　SLI
		- Availability, Latency , Latency
	- ↑のあとSLOが決められる「時間と割合は？」　
		→ 高くしすぎるのは注意
		- 最初はとりあえず決めて、徐々に改善していくでいいと思う
- Postmortem
	- Post mortem : SLI/SLOをベースにしたモニタリングの結果で、インシデントがあったことに対しての対策どうしよっか、みたいなことを考えるもの
	- tool : PagerDuty
- Error Budget
	- エラー予算：SLOとは逆の意味で許容可能なエラー率のこと
	- PMが責任もを持っている
	- このタイミングでりり0鮨定位？
	- 冗長化などの信頼性を高める実装に時間をさくべき？
	- とかの会話ができるようになる 

## 20:35~	Spannerのパフォーマンス チューニングとよくあるミスについて by @sinmetal

- ソリューションチーム(得意領域を持つエンジニア)でやってます
- Spannerの話します
- どんな感じに開発してる？
	- Golang利用
	- Spannerにアクセスしてるライブラリ :社内で作ったツール、Cloud Client Library
	- UnitTest :本物のSpanner を動かしている
	- 節約のために一つのSpannerをみんなで使ってる
- 開発中に起こったミス
	- 失われたInstance
		- Teraformで管理してる
		- 開発環境は権限を持ってる人がいる
		- うっかり消しちゃった！ということがあった
		- クラウドコンソールで削除とかは時間が地味にかかる
		- コンソールでDB消すのは慎重に
	- Session leak
		- Queryの結果を1件だけ取得したい
		- iterはStop()させないと、Sessionを掴んだままなので、必ずStop()を呼ぶ必要がある
		- 1件だけだから。。。とdeferでcloseしないとこういう目にあう
		- どうやって気づいたか
			- モニタリングのMetricsにSession数があるので、とりあえずこれをみる
			- 負荷試験のときに気づいた
			- Applicationを動かし続けた時に、Session数が右肩上がりに増えていけばかなりの確率でLeakしてる
	- Transactionもれ
		- ReadWriteTransactionの中で、通常のClientを使ってしまうケース
		- どうやって気づいたか
			- 小さく気づくにはコードレビュー
			- 将来的には静的解析で検出したい
			- 静的解析だけしてるおじさんが社内にいるのでその人が多分つくる
	- LikeとStarts_with
		- パラメーーたで渡す値でStartWithを行う場合、Text Like @paramではなく、
		- STARTS_WITH(TEXt, @param)を利用する
		- likeを利用した場合、indexが聞かず、tableをfull scanしてしまう
		- consoleで text like "hoge%" を実行すると問題ないので気づきづらい
- SpannerのPerformanceチューニング
	- セッションのライフサイクルの管理
		- Spannerのセッションは作成に700msくらいはかかる
		- なるべく裏セッションを作るようにしたい = セッションプールさせたい
		- 設定値色々あるが、デフォルトのまま最高なことはない
		- なので無難に「MinOpened（開いた時にセッション維持してくれるやつ）」「MaxIdle(アイドルセッションの最大数)」は設定しておいたほうがいい
		- 「WriteSessions(Sessionプールの中にBeginTransaction済みのSessionが生成される)」は設定すると遅くなるので注意
			- 優先的にBeginTransactionを利用するが
			- リクエスト数が少ない時、昔にBeginTransactionされたものを利用してしまう
		- Transaction内でNot Foundを発生させる
			- Transaction内でTableに存在しないKeyでReadRowするとTransactionがAbortされやすい
			- 基本的にはInsertでぶつけにいく
		- Transaction内で広い範囲をQueryする
			- 狭い範囲をQueryを実行させる
			- Abortしやすい
			- 知見はgcpub/nouhau にまとまっている
	- Queryのチューニング
		- table設計
			- データサイクルを考える : いつ誰がInsert,Update, Delete, Selectするのか
			- 正規化とかはさほど考えたこと無い
		- Index
			- 辞書順に並んでるだけ
			- 基本的にはCloud Datastoreと一緒
			- Indexは貼る必要がある
			- 自分で最適な順番を考えてあげる必要がある
				- scanした時に、ひとかたまりが引っ張ってこれるようにしてる
		- Shard
			- 単調増加するカラムにindexを貼る場合、hotスポットが出来てしまうことがある
			- それを回避するたmにshard columnを作成する
			- shardはindexを早くするためにするもの
			- shardの値が大きいと分散しやすくなるので、selectは遅くなる
			- shardの値は0~100(相当大きいシステムでも)で十分
		- インターリーブ　
			- 親と子供を同じ場所に置いてあげる
	- クエリのPerformanceチューニング
		- Query Statsで行っている
		- テーブルの中に値が保存されているので、クエリを書くこともできる
		- データが少ない状態で見てもしょうがないので、一杯データを入れてやるとか負荷試験をしたりしてチェックする
		- 本番環境もちょいちょい見てあげる必要がある（データがだんだん増加するので）