私的アーキテクチャの検証ベストプラクティス

半年くらい様々な検証に携わってきたので、その内容を抽象化してまとめてみました。

ほぼ我流で進めてきたので、私的にはベストプラクティスなつもりですが、もっといい方法がある可能性は否めません。
("私的"と保険をかけているのはこのためです。)
ていうか、もっといい方法は絶対ある！でもあんまりこういう情報って出回ってない！ので改善点あったら教えてくださいm(__)m

用語の定義
------------------------------
###"アーキテクチャ"
本文書では"アーキテクチャ"という言葉を「あるソフトウェアを動かすために必要なサーバ群とミドルウェアの構成」という意味で使います。

###"検証"
本文書では"検証"とは大きく以下の2種類の検証を扱います。

1. アーキテクチャが機能要求を満たせるかを確認する機能検証
2. そのアーキテクチャで、どんなマシンスペックなら非機能要求を満たせるかを確認する性能検証

免責
------------------------------
私の会社はオンプレミスで構築しているため、クラウド利用が前提の場合、検証内容もう少し緩くしていいとかはあるかもしれないです。
その辺りの匙加減は分かりませんので悪しからず…。

検証設計をする前に…
------------------------------
そもそも検証を行う目的が明確でないと、検証内容をいくら考えても意味はありません。
という訳で少なくとも以下の情報が出揃うまで、アーキテクチャの検討を頑張りましょう☆

###機能要求
そもそも作ろうとしているソフトウェアは何を実現しようとしているのか、どんなユーザ体験を提供しようとしているのか
そのユーザ側の要求によって、システム側にはどんな要求が生じるのか。明確にしておきましょう。

###非機能要求
ソフトウェア自体の機能だけでなく、2重障害を許容するか、レイテンシーはどれくらいまで許容するか、などなど非機能のところも定める必要があります。
ここは観点が多すぎて大変なんですが、弊社ではIPAの「非機能要求グレード」を参考に作成しました。

よければ参考にしてみてください
[非機能要求の見える化と確認の手段を実現する「非機能要求グレード」の公開](https://www.ipa.go.jp/sec/softwareengineering/reports/20100416.html)

###アーキテクチャの仮案
検証する対象のアーキテクチャが
"仮案"と付けている理由は、検証の結果によって、そのアーキテクチャが覆る可能性があるからです！(ありました…。)

具体的には以下のような情報が出そろっているといいかなと思います。

* サーバーの台数
* ネットワーク構成
* それぞれのサーバーにインストールされるミドルウェア
* 障害時の対応

機能検証の進め方
------------------------------
それでは具体的に検証の設計から実行までの手順を説明していきます！
大きくは下記のような流れで進めていきます。

* 考えるフェーズ(かっこいい言葉を使うと検証設計)
    1. 「何が見たいのか」を明確にする
    2. 必要な検証環境を考える
    3. 確認項目と、その確認方法の洗い出し
    4. 具体的な検証手順を書き出す
* 手を動かすフェーズ
    5. 検証環境の構築 / スクリプトの準備(必要であれば)
    6. 検証実施！

それでは一つ一つ詳しく見ていきましょう！

###1.「何が見たいのか」を明確にする
大前提としての検証の目的を再確認しましょう。
まず最初に「これが確認できないと不安」という観点をできるだけ挙げます。
よくある観点としては以下のようなことです。

* 機能面での不安
    * 機能要求が満たすよう動作してくれるか
    * 障害時、想定しているようにフェイルオーバしてくれるか
* 性能面での不安
    * 通常時の負荷の時、非機能要求を満たせているか
    * ピーク時の負荷の時、エラーや極端な遅延が発生しないか

それから、「これは確認すべき」「ここは最悪ミスっても後でどうにでもなる」などプロジェクトの状況に応じて、何を確認するかを整理していきます。

###2.必要な検証環境を考える
見たいものを検証する時に必要な検証環境を考えましょう。

▼ 最低限以下の情報を揃えることがゴールです。

* サーバーは何台?
* それぞれのサーバーの
    * OSは?
    * インストールするミドルウェアは?
    * マシンスペックは?
        * CPUモデルとクロック数
        * CPUのコア数
        * メモリ
        * ディスク
            * HDDかSSDか
            * サイズ
            * IOPS
* ネットワーク
    * 外部ネットワークか内部ネットワークか
    * 帯域幅

####性能検証時の注意点
基本的にはクラウドでインスタンスを立ち上げて、負荷をかけた時のリソース消費を見て、マシンスペックを上げるなり下げるなりして、非機能要求を満たす値を見つける、といった感じになると思います。
ので、マシンスペックは最初は仮で置くしかないんですが、この時は「これくらいあれば大丈夫だろう」というスペックを勘で見積もるのがいいと思います。
1Core1GBから初めてちまちま上げていくよりはそっちの方が手っ取り早いはずです。

###3. 確認項目と、その確認方法の洗い出し
具体的に検証では何を確認するのか、それはどうやって確認するのか、確認した結果をどう記録するのかを検討しましょう！

▼ よくある確認項目を思いつく限り羅列すると下記のような感じです

* リソース消費
    * CPU使用率
    * メモリ使用率
    * IOPS
    * Net IO
    * Load average
    * ディスクIO
* 処理関連
    * レイテンシー
    * エラーが発生しないか
* DB関連
    * コネクション数
    * データ件数

▼ また、私がよく利用する確認方法は下記の通りです。

* リソース消費
    * dstat -tcmlrdn で全部見れます
* 処理関連
    * スクリプトにレイテンシーを出力したり、負荷テストツールのプラグインを使ったり…
* DB関連
    * コネクション数
        * MySQL - mysqladmin -h <IP of MySQL server> -u root -p -i 60 extended-status|grep conn
        * Cassandra - nodetool netstats
    * データ件数
        * MySQL - SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'your db name' AND TABLE_NAME = 'your table name';
        * Cassandra - SELECT COUNT() FROM table name もしくは nodetool cfhistograms(estimateの値)

####余談: リソース消費記録にはddstatが便利です
リソース消費を監視する時は大体dstatを使っているんですが、数字だけ見てても全体像がよく分からん、グラフが欲しい、と感じることが多々あります。
そんな時はddstatが便利です！

↓ こちらの方が作ってくださったツール
[dstatリアルタイムグラフ化ツール ddstat を作りました](http://so-wh.at/entry/2014/02/16/dstat%E3%83%AA%E3%82%A2%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%B0%E3%83%A9%E3%83%95%E5%8C%96%E3%83%84%E3%83%BC%E3%83%AB_ddstat_%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F)

データを保持してくれるDatadogが無料アカウントだと24時間しかデータを保持してくれないのですが、
ササッと結果を保存すればいい話なのであんまり苦になったことがありません。

あと大袈裟かもしれませんがZabbixやMuninなどの監視ツールを入れるのも一つの手かもなと最近思います。

####余談2: 様々な監視をする時には screen が便利！
様々な監視を行う時、Linux初心者だった私はアホみたいにたくさんのウィンドウを開いていました…。
screenを使えばそんなことをしなくて済みます！

私は基本的に

* screen
* 監視コマンド実行
* ctrl+a d でディタッチ

しか使っていないですが、とても便利で助かっています。
詳しい使い方は下記の記事を参考にしてみてください。
[screenコマンドの要点](http://qiita.com/ryounagaoka/items/8203e9c149b542986c92)

###4. 具体的な検証手順を書き出す
ここでは「この資料通りにコマンドをポチポチ打っていけば検証が終わる」レベルまで検証手順を作りこむのがゴールです。
私は下記の画像ような感じで、

* 目的、やりたいこと
* 実行するコマンド / 作業
* コマンドを実行するサーバー
* 備考

を1ステップ1ステップ書くようにしています。

<img width="910" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/150569/f49712ba-b401-332b-5c1d-b15f89448b42.png">

正直ここはもう少し工夫のしがいがある気がするのですが…、他にうまい方法も思いつかないので、現状はこのフォーマットでまとめています。

###5. 検証環境の構築 / スクリプトの準備(必要であれば)
それでは検証を行うための環境を構築、またスクリプトを実装していきましょう！
ここに関しては個々の検証によってやることが違うので、本文書では詳しくは述べません。
大体一番トラブル多いのがここなんですけどね…。

また、この時絶対！！！にやっておくべきなのが環境構築の手順を整理してメモしておくことです。  
本番でデプロイする時や、チームメイトが似た環境でなんらか実装する時、未来の自分に向けて…、将来役に立つ瞬間は高確率で訪れます。
手間はほとんどかからないので、是非是非メモしておきましょう！！
また、AnsibleのPlaybookでも作っておくと同僚に崇められるかもしれません。

###6. 検証実施！
あとはやって結果をまとめるだけです。
問題なければすぐに終わるでしょう。
まあ大抵問題出るんですけど…。

おわりに
------------------------------
お疲れ様でした。

私なりの検証方法ベストプラクティス、いかがでしたでしょうか。
少しでもお役に立てれば幸いです。

また、フィードバック等ございましたら是非お願いします！
それではよい検証ライフを～。