Supervisorでnginxを管理してみる

daemontoolsを使っていますが、設定や導入の分かりやすさやからSupervisorを使いはじめています

http://supervisord.org

インストールや細かい設定は省きますが、/etc/supervisord.confに外部設定ファイルを参照するようにしてデーモンを管理するのがいいようです。

[include]
files = /etc/supervisord.d/*.conf

nginxを追加してみる

/etc/supervisord.d/nginx.confを新たに作成してSupervisor配下にいれます。

[program:nginx]
command=//usr/sbin/nginx -c /etc/nginx/conf/nginx.conf
process_name=%(program_name)s
numprocs=1
stopsignal=QUIT

起動に成功するとsupervisorctlで確認することができます

$ supervisorctl status
nginx                            RUNNING    pid 11667, uptime 14:46:21

再起動もsupervisorctlで行います

$ supervisorctl restart nginx
nginx: stopped
nginx: started

nginxにHUPシグナルを送りたい

nginxはHUPを受信すると、設定ファイルを読み込んで、エラーがなければ 新しい設定ファイルを適用してくれる仕組みがあります。

新しい設定が適用されると新しいworker processが立ち上がり、古いworker processは緩やかにshutdown差し替わってくれるので、実際はこちらを使いたい場合が多いでしょう。

supervisorctlには特定配下のデーモンにHUPを送る仕組みはないようなので、直接HUPを送ることにします

$ supervisorctl status nginx | sed "s/.*[pid ]\([0-9]\+\)\,.*/\1/" | xargs kill -HUP

これで新しい設定を適用することができました

参考: http://webos-goodies.jp/archives/deploying_tornado_with_supervisord.html

久々の投稿、、、

Amazon S3使ってみた

今更ながら使ってみた。
Amazon Simple Storage Service

サーバのDiskが週に1Gとか日に1Gとか普通に埋まっていくのでなんとかしたい。

概念的に増やしたい!願ったり感じたり信じたりすると増えるみたいのが欲しい。
容量とか気にしなくて良いし、物理的に増設していくのも疲れるからね。

実際に使ってみる

S3Foxを使ってブラウザで管理。S3Foxでファイルの追加とかもできるけど、めんどくさいのでそこはCUIで!

Amazon S3用のコマンドラインツールs3cmd

s3cmd --configure
# ...いろいろ設定...

s3cmd ls
s3cmd ls s3://hoge
s3cmd put test.csv s3://hoge

こんなURLでアクセスできる。

http://hoge.s3.amazonaws.com/test.csv

以下をTrueにしておくと誰でも閲覧可能に

$ vim .s3cfg 
acl_public = True

さくさく動いて楽しいかも。

ApacheBenchとってみた

他でも計測している人がいましたが一応。1.15Mのファイルを"ab -n 100 -c 10"で計測

$ ab -n 100 -c 10 http://hoge.s3.amazonaws.com/test.csv
:
Document Length:        1214170 bytes

Concurrency Level:      10
Time taken for tests:   76.210336 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      121456000 bytes
HTML transferred:       121417000 bytes
Requests per second:    1.31 [#/sec] (mean)
Time per request:       7621.033 [ms] (mean)
Time per request:       762.103 [ms] (mean, across all concurrent requests)
Transfer rate:          1556.34 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      138  153  13.4    162     172
Processing:  2112 7149 1347.2   7362    9166
Waiting:      146  167  16.2    171     207
Total:       2284 7303 1351.6   7502    9336

Amazon CloudFrontも使ってみました。同様に計測
CloudFront

$ ab -n 100 -c 10 http://xxxxxx.cloudfront.net/text.csv
:
Document Length:        1214170 bytes

Concurrency Level:      10
Time taken for tests:   24.979753 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      121474600 bytes
HTML transferred:       121417000 bytes
Requests per second:    4.00 [#/sec] (mean)
Time per request:       2497.975 [ms] (mean)
Time per request:       249.798 [ms] (mean, across all concurrent requests)
Transfer rate:          4748.93 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       23   72 300.8     41    3046
Processing:   442 2354 2155.8   1244    8813
Waiting:       24   57  59.1     43     349
Total:        467 2427 2202.8   1270    8836

時間や混みぐあいで変わってくるようですが、どうでしょう。

トラブルに強いWebアプリケーション

個人的にですが、Webアプリケーションを作るときに注意していることです。

URLとクラスのマッピング

URLとそこで操作するクラスの名称を一致させたり、似た名前にしておくと色々よい事があります。

  • ユーザ情報を表示するURL
 http://example/user/akihito/profile
  • ユーザ情報を取得するクラス(ユーザ情報を表示するときに使用)
 user = new User('akihito');
 user.profile.age;
 user.profile.email;

つまりURLとクラスがマッピングするように設計しておくわけです

 /user/akihito/prfile  <=>  user(akihito).profile
 # ユーザ情報の更新
 /user/akihito/prfile/update  <=>  user(akihito).profile.update({age=>99})
 # ユーザの削除
 /user/akihito/delete  <=>  user(akihito).delete()

こうしておくとトラブルやバグに遭遇したときに問題箇所が特定しやすくなります。
また、update,deleteの名称をURLに含めることで更新系の操作を別サーバに振り分ける布石にもなります。

例外処理

例外処理には例外オブジェクトを使用することをお勧めします。
PHPであれば標準のException,try,catch、PerlであればException::Class,eval,$EVAL_ERROR($@)があります。フレームワークが提供している例外クラスを使うのもいいですね。

下層のクラスで"throw Exception"しておけば、上層クラスで補足することができます。例外処理を標準化して、チーム全体で統一したエラー処理を行うようにしておきましょう。

ログ

参照系の操作なのにPOSTメソッドを使ってクエリーをアクセスログからなくしてしまうのは非常に残念なことです。

 http://example/search
 http://example/search?q=hoge

例外処理のエラーメッセージや場合によってはPOSTメソッドのクエリーをエラーログ等に吐き出しておくのもいいですね。ユーザの動きが非常に追いやすくなります

セッション

セッションに入れた値は可読性が失われます。また経路によってセッションデータを書き換えるような設計はトラブルの元になります。
自分はセッションに何を入れるかは、どちらかといえば慎重派です。小さいセッションで最大の効果を得られるようにすべきです。

まとめ

トラブルやバグには必ずあります、少なくすることはできますが、なくなる事はないです。
遭遇したときに問題箇所を特定し修復できるように事前に準備しておくことが、トラブルに強いWebアプリケーションだと思います。

良いお年を〜

絶賛放置プレイ中のこのブログですが、来年もよろしくお願いします。

今月こっそりアップしたモジュールですが、そのうち何処かのブログで解説したいですね。

http://search.cpan.org/~akihito/File-Stat-Trigger/

心霊写真変換がMixi砲をくらった話とか

はてな界隈では、さほど話題にならなかった心霊写真変換ですが、実はGIGAZINEに載った経緯でmixiの注目ニュース入りし、かなりのアクセス数になりました。

経緯としてはこんな感じです↓

  • GIGAZINEに載る→mixiニュースに載る→mixiユーザが日記を書く→注目のニュース入り→アクセス殺到

Yahoo!砲ほどではないのですが、ユーザが写真を変換しまくるものだからエラい事に...
mix自体あまりやらないのですが、こんなに凄まじいとは思いませんでした;;

さて、このジェネレータですが、はてぶの数は今日現在で35程度。
何が言いたいのかとゆーと、はてぶのブックマーク数だけが全てじゃないんだなぁと思った訳です。
あとエントリー書いて知り合いに教えたくなるネタってのもありますね。

まぁ画像を重ねてるだけなので、ネタ的にはブクマされるようなものではないのですが、、、あちこちのブログに書かれた為に話題にはなっていたようです。


ついでですが、顔ラボAPIを叩くモジュールをCAPNにアップしました、遊んでくださいまし。

これでようやくCPAN Authorですね。

心霊写真変換で目線を選択できるようにしました

心霊写真変換つくりましたの続きです。

顔ラボAPIが1日あたり200回?しか叩けないようなので、目線を選択できるようにしました。
目線をなしにするとAPIを叩かないので多少制限回避になるかなと。

個人的には「目線を入れたほうが心霊写真ぽいな」と思っていたのですが、要らないという要望もあるようなので。

もう少し増やしてくれねーかな>200回

APIの利用制限を上げていただきました。顔ラボさんありがとうございます!(2008・4・14)