Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

最近のソフトウェア開発の暮らしぶり

メモなので雑に書いています.

キャパシティプランニングした

とある事情があってキャパシティプランニングをやったのだが,経験者(id:hitode909)と一緒にやったので大変参考になった.

キャパシティプランニングとは,ひらたく言えば「この機能でシステム耐えられそうですか」というのを計画して,大丈夫そうですね,とか,DB増強しないとやばいね,とか,そういうのを考えること.

今回はDBが耐えられるか,そしてアプリケーションサーバ(Plack)が耐えられるかを調査した.

DB

DBのキャパシティプランニングでは,IOが刺さらないかを調査した.RDBMSは最終的にディスクにデータを書き込むのだが,AWSとかAzureとかのクラウドプロバイダが提供するサービスでは,IOの能力に制限がある.まあ実際のハードウェアでも無限の速度でIOをやったりはできない.そこで,R/Wの量を前もって見積って,ハードウェアのI/O性能が溢れないかを確認する.溢れちゃうと,I/Oが停止して,RDBMSは停止してしまう.困る.AWSでは入出力スループットにIOPSという単位を使っているので,さらにこれに換算したりする.

具体的にはこういう事を調べた.

  • そのエンドポイントはピークタイムで何回叩かれるのか
  • そのエンドポイントは最悪(平均|1σとかいろいろな基準を考えられるけど,今回は最悪値で良かった)どのくらいのクエリを発行し,そのうちReadは何回,Writeは何回なのか
  • 1回のクエリでどのくらいのI/Oが発生するのか
    • RDBMSに尋ねると行あたりのBytesなどが得られるのでここから推測する
  • 今RDBMS(を載せているEC2(がカキコしているEBS))は既にどのくらいのI/Oを捌いているのか
  • 機能のリリースによってI/Oの量はR/Wでそれぞれ何割増になりそうか
  • I/Oが増えたことにより必要なIOPSはどのくらい増えるか
  • IOPSがEBSの限界に当たらないか

Worker

Plackワーカが耐えきれるかも調査した.

まずワーカってなによという話.WebアプリケーションはアプリケーションサーバがHTTPとアプリケーションコードとの橋渡しをやる.今回Perlで開発している我々はPlackを使っていて,PlackはPreforkモデルだ.Preforkについては以下参照.

blog.3qe.us

Preforkモデルでは,1つの親プロセスに子プロセスがたくさんぶら下がっていて,1リクエストを1プロセスで処理する.この処理用プロセスをワーカと勝手に呼んでるけど,巷では違うかも.

リクエストを処理する間,ワーカはリクエストによって占有される.そしてレスポンスを完了するとワーカはまた次のリクエストを処理できるようになる.

バックエンドサーバが同時に起動しているワーカの数には限りがあるので,例えば2台のサーバにそれぞれ100発ずつワーカが起動している場合,200リクエストを同時に捌けるということになる.これを超えるといくら他のリソースが空いていても,リクエストを処理することができない状態になる.

で,この限界に抵触しないかを調べるということをやった.

ここで面白かったのは,占有秒数を使って計算したという点.ふつう,同時に200リクエストまで,と聞くと,同時接続数を計算すればいいかと思うけど,リクエストには処理時間というのがあって,たとえば処理に10秒かかっていては同時に200回リクエストが来なくとも,来襲するペースによってはいずれワーカが枯渇してしまう.したがって,リクエストがどのくらいワーカを占有するのかを使って計算することになった.

そのエンドポイントがどのくらい叩かれるかというのはあらかじめある程度分かっているから,どのくらい占有するかを確認する.Redashとかのツールを使って,nginxのログを漁ると,taken_secといった項目があるので,それに秒間リクエスト数を掛けると,そのエンドポイントの秒間”延べ”占有秒数が分かる.

$$ taken_{total} = taken\_sec \cdot N(req) $$

ここでワーカに目を移す.例えば200ワーカあるとすると,1秒間あったとき,延べ200秒分の処理能力を持っているということになる.つまり,先程の秒間延べ占有秒数が200秒を超えなければ,ピーク時もワーカに限っていえば耐えきれるということになる.200秒を超えると,じわじわアイドルなワーカは減少していき,最終的に全てのワーカがリクエストを掴んでしまって新規リクエストをつかめなくなり,サービスとしては死亡する.

市役所で考えると,職員が10人居るとき,30分話をする人が30分以内に10人以上出現すると市役所としては破綻してしまう,みたいな話.

もしくは,分岐したレールが平行に3本あって,同時に3本まで列車が進入できるけれど,通過しきるまで次の列車は進入できない,といったとき,列車の進入頻度と通過に必要な時間は分かっていて,これで通勤ラッシュは破滅しないだろうか,といったことを考えている状態.ここから改善するとなると,列車のスピードを上げたり,レールを並列にする,といったことができる.Webアプリケーションも同じで,リクエストにかかる時間を短縮したり,ワーカを愚直に増やしたりする.でもワーカを増やすと当然お金がかかる.

Redash

ところで今回初めてRedash使ったけど良かった.Redashは,Athena(につながってるS3に保管されたログ)や,MySQLといったマルチバックエンドに対応していて,SQLを書いて発行することでテーブルを出したり,グラフにしたりできる便利なやつ.マルチバックエンドになったKibanaに近いかな.アクセスログの集計とかに使った.当然バックエンドによって書けるSQLが違っていて,Athenaでは書けるけどMySQLでは書けないといったことはある.

開発もしている

ここ最近は機能開発をやっていた.

学ぶことがいろいろある.

例えば設計に先立ってやるべき見積りとか仕様の詰めが甘くて後から設計が耐えられなかったり,逆にこんなに複雑な設計にする必要ない,といったことが起こったりする.手練れのエンジニアは仕様策定も設計も上手くて,問題のために適切な複雑性を選ぶことができる.もちろんシンプルなのが一番良いのだけれど,現実の問題がシンプルではない場合は,シンプルでない設計が必要になることもある.

後から,既存の他の機能との自然な統合ができていないことが分かって,つまり同時に動かすと破滅をもたらしたり不整合をもたらしたりするということが分かり,よしなに調整するといったことも起こる.

開発しながら設計もするとなると,実装に気を取られて,なんでこういう設計になってるのかを疑わずに実装に突っ走ったり,なんでこれが必要なのか分からなくなったりする.

テスト.アサーションルーレットという概念を知った.PICTというツールでペアワイズ法を試してみようとしたけどテストケースが少なくて別に使う必要なかったということもあった.

テストに対する考え方,というかテスト計画が自分と同僚とでは違うところがあっておもしろい.自分は事前に入力で内部的にありえる全パターンについて,入力と出力とを考えて……みたいな事を考えていた. しかし同僚が考えていたのは,こういう時はこういう出力が欲しい,というユースケースで,全パターンはわざわざテストしなかったりする.ようは要件を満たしているかを考えている. 要件について考えているのだから,内部のパターンについて網羅する必要はない,ということなのだろうか.たぶん,ブラックボックステストとかホワイトボックステストとかに通じるのかもしれない.

よくできていて,頑丈で,使い勝手が良く,テストしやすく,運用しやすい,そういう設計ができたい.

継承.自分は見たものをそのままクラスにして……と考えがちだけど,クラスにする以上は問題解決のために必要なレベルで,目的に即して抽象化する必要がある,ということを学んだ.

blog.3qe.us

というか,うまく抽象化しないと,設計も実装も現実より複雑になってしまう.

計画もしている

ンヶ月規模の計画・設計・開発は初めてだったのでフニャフニャになりつつも,こうして振り返りや学びを得ているので,未来は明るいような気もする.

仕様のほうばかり気を取られていたので,キャパシティプランニングとか事前の計画に入れておけば良かったなと思っている.

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?