一からマイクロサービスの開発フローを作った話

※ 2016年の記事なので、すでに古い情報が多いです。

今の会社で、全社の外部サービスで利用できるAPIを作ってね、という話があったので、環境構築からコーディング、運用まで一人で行っている。
基本はAWSのサービスを利用し、ログの保存だけGCPのBig Queryを利用した。

 ※ 2017/10/13 追記
このときの経験を踏まえて、コンテナでの環境構築を行ったので記録した。
  → [一からAPIサーバの開発フローを作った話〜コンテナ編](https://qiita.com/tomoyamachi/items/6862cd8ffe220689f6c0)



## 関連記事
- [マイクロサービスで調査しやすいログをつくる
](http://qiita.com/tomoyamachi@github/items/672be517102ebab37f10)
- [マイクロサービスのテスト作成方針
](http://qiita.com/tomoyamachi@github/items/a1240ac1cb451a8425b1)
- [マイクロサービス作成時におこなった負荷対策](http://qiita.com/tomoyamachi@github/items/3bd2242cb755fcecbf28)
- [deployフローに関しての振り返り](http://qiita.com/tomoyamachi@github/items/c85e73ada42ab5d564eb)
- [ウェブサービス構築時に導入する、開発が3倍速くなる仕組み](http://qiita.com/tomoyamachi/items/1e2b9fffff8b356822cd)

## 簡単な要件
- ゲームなど自社で利用するユーザアカウント情報を1つにする
- 現在のアカウントで引き続きサービスは利用できる
- アカウント以外にも各アイテムのデータやらを管理し、使用回数などをログとしてもつ

また、現在それぞれ別サービスになっている、以下の社内サイトのデータも一元管理。
今の会社が、企業に営業をし、もらった賞品をゲームユーザに配布するという仕組みのため、これらも同じように管理することにした。

- 営業管理ツール
	- 賞品を提供してもらう企業への営業内容の履歴
- 企業用レポートサービス
	- 賞品を提供してもらった企業へレポートを作成し表示する

## 1つのマイクロサービスサーバ周りの構成
![server_production.png](https://qiita-image-store.s3.amazonaws.com/0/14275/0cfe795c-639e-b6a9-d139-57c9d15481b5.png "server_production.png")


## サービス構成
以下のサービスが連携しあう構成。
これらはそれぞれ別のプロジェクトとして作成する。

マイクロサービスの利点は、
責任箇所の明確化にできることなので、
よほど関連しているデータ以外は分ける。

- アカウント管理サービス
- アカウントリソース管理サービス
- 賞品 / 顧客情報管理サービス
- その他、開発中サービス

## 守りたかったこと
- エラーが起こることは許容。データが壊れた場合、元に戻せるようログを残す
	- 短い期間での開発、かつ、仕様が頻繁に変わる案件だったため、復元可能な状態にすることを優先。
- 1つのdeployサーバで、各サービスのステージ/本番サーバにdeploy/ログ監視ができる
	- 複数のサーバ間が通信しながら処理を行うため、tail -f *_error.logなどで一括で見たい

※ 6/29追記 各種ログに関する記事を書いた。
[マイクロサービスで調査しやすいログをつくる
](http://qiita.com/tomoyamachi@github/items/672be517102ebab37f10)

### その他メモ
- LBの下にひもづくサーバのログはdeployサーバにすべて送られる(どのIPからのログかは分かるように)
- 5日以上経過したログはgzip圧縮されS3にアップロードし削除
- 集計で利用するログはGoogleBigQueryへ保存

## AWS関連図
本番の環境は基本的にAWSを利用。
利用しているサービスも含めて記載すると、
![aws_production.png](https://qiita-image-store.s3.amazonaws.com/0/14275/de5eb24c-2a38-1a1b-a95d-12eb6d5a5b2c.png "aws_production.png")


## 障害検知
処理エラーについては、エラーが発生時、メールで発生したサーバIP/発生したendpoint/エラー内容などが指定されたメール宛に送信される。

## 状態監視
上記のAWSサーバ以外にも画像サーバなどを一つのサイトで確認できるようにしたいので、[grafana](http://grafana.org/)を利用。
構築手順は[ここ](http://blog.serverworks.co.jp/tech/2016/03/11/play-with-grafana-1/)など。

## 開発フロー
### 開発
テスト駆動 / チケット駆動で開発。
※ 6/30追記 テストの方針を、別記事として公開した。
[マイクロサービスのテスト作成方針
](http://qiita.com/tomoyamachi@github/items/a1240ac1cb451a8425b1)

通常これを徹底するのは難しいが、一人で進めたので大体テストのカバー率もよく、チケットを見れば課題がわかった。

![platform_dev_env.png](https://qiita-image-store.s3.amazonaws.com/0/14275/913defa6-c28a-72af-a9c9-759a8ae85b0b.png "platform_dev_env.png")

### 負荷対策
- テスト実行時には、サービス内で発行されるすべてのSQL文を出力し、多用される内容についてはキャッシュに保存するよう修正
- my.cnfに`log_queries_not_using_indexes`を設定し、SLOW QUERYを見ながらINDEXがはられていない部分にINDEXを貼る

## DEPLOYまでのフロー
![tomoya_delivery.png](https://qiita-image-store.s3.amazonaws.com/0/14275/9210cce4-8ba2-516a-09b3-994fab7db001.png "tomoya_delivery.png")

### 本番への取り込み
Gitで管理しているマスターレポジトリに対し、pull requestを送ると、Circle CIでテストが行われる。
CircleCIで行うことは開発で行ったテストと変わらないが、環境を1から設定してテストを行うので、開発サーバだけで動く、という問題は解決する。

Circle CIのテストに成功したもののみMergeされる。

### 本番へのリリース
masterに同期されたあとは、stagingサーバへリリースして再度、動作確認を行う。

本番サーバへリリースする場合、各種ログを必ず確認する。

## その他
- 開発時、テーブルのmigrationを自動化

※ 12/29追記 migrationや管理ツールの自動化について書いた
[ウェブサービス構築時に導入する、開発が3倍速くなる仕組み](http://qiita.com/tomoyamachi/items/1e2b9fffff8b356822cd)

## 反省点
- 利用言語がPHP
	- 会社のフレームワークが、PHPを利用しており、フレームワークを使ってみるとよいとのことだったので、PHPでの開発になった。すべて一人で構築するなら、より適した言語を選べばよかった。
	- ただし言語を変更するときでもインタフェースだけは担保できるよう、Cucumberによるインテグレーションテストは切り分けてある
- 初期は本番環境構築にAnsibleを利用していたが、途中でメンテナンスをやめた
	- 時間がなさすぎて、最終的にはAMIがあるからいいや、ってなった。
	- もちろんAMIをベースにして、サーバを起動し、起動時のスクリプトでコードを最新化したり、という工夫は行っているが...