2009年10月アーカイブ

本日(2009/10/22)の午前5時頃より、本BlogとFemoLIMILICにアクセスができない状態になっていました。
利用していて頂いている方にご迷惑をおかけしました。

アクセスが出来なくなっていた原因は、自宅サーバが落ちていたということですが、なぜ落ちていたかというと、UPSが壊れたっぽいからです。
現在はUPSなしで動いてますので、停電があるとまた止まってしまう可能性があります。こちらの対策も早めに行うつもりです。
(そういや、ここ何年か停電を経験してないかも)

これまで使っていたUPSは、三菱電機のFREQUPSの350VA製品。 実は6年ぐらい使っていました(ここが駄目 バッテリがもうだめだったのでしょう。交換考えないとなぁと思っていた矢先でした。

UPSが壊れて気になるのは、その廃棄方法です。調べると、鉛が入っているので通常のゴミとして捨ててはならないようです。

元祖ワシ的日記2.0 無停電装置の廃棄で困った

そこで調べたところ、オムロンのUPSを新規にUPSを購入した場合に、オムロンが他社のUPSでも無料で引き取っていることを発見。

UPSリプレイスサービス|製品情報|OMRON 電源機器

APCでも同じようなサービスやってる

Trade-UPS(UPS買い替え促進プログラム)

ということで、オムロンもしくはAPCのUPSを買い直して、こちらのサービスを利用して今のUPSを引き取ってもらおうか検討中。

350VAクラスのUPSなら、Amazonで結構安いNe。


10月は偶数月。
そして偶数月といえば、こちら。


WEB+DB PRESSで連載させて頂いている「大規模Webサービスの裏側」の4回目がVol. 53に掲載されます。
第三回目のデータベース設計編に続いて実運用編となっています。

内容は、OSの設定、ファイルシステムのチューニングから、MySQLの設定と監視の話です。1000台を超えるサーバを管理・運用していく上でのポリシーなども混ぜて書いています。
紹介している設定などは大規模なサービスにだけ利用できるものではなく、小規模な運用でもパフォーマンス向上のために参考にできることが多いと思います。 松信さんの本や、アメブロさんの本と内容が被っていますが、8ページと手軽に読めると思いますので、ぜひお手をとって頂ければと思います。

その他Vol. 53には、mixiと同じくというか、規模がそれより大きいかもしれないYahoo!オークションの運用についての特集があります。
10年以上サービスを続けているということで、さまざまなノウハウや経験がつまった記事になっています。やはり、他社の事例を読んだり、想像したりするのは面白いですね〜。参考になりました

あわせて読みたい

(即納できるみたいです)

【オマケ】
Software Designの11月号にはバタラさんのインタビューが載ってますね。

PSGI/Plackにおいて、非同期にレスポンスが返せるstreamingという仕様/機能が追加されました。
PSGI/Plack streaming is now complete

これを使うと、streamingをサポートしたサーバから非同期/nonblockingにhttpやGearmanを利用して外部へ問い合わせを行い、その結果をレスポンスしたりできます。

また、これがPlackで既に実装済みなので、非常に短いコードでサーバの実装ができちゃいます。
すばらしいですね。

すでにmiyagawaさんが、この機能を利用した非同期Web Framework「Tatsumaki」を書かれています。 イベントを扱う部分が隠蔽されているので、これを使うとさらに簡単に実装できます。
すばらしすぐる。

ここでは、簡単に外部へAnyEvent::HTTPを用いて、HTTPリクエストを行うサンプルを書いてみます。

use AnyEvent;
use AnyEvent::HTTP qw//;

$AnyEvent::HTTP::MAX_PER_HOST = 20;

my $url = 'http://localhost/tmp/sleep3.cgi';

my $hanlder = sub {
    my $env = shift;

    my $cv = AE::cv;
    AnyEvent::HTTP::http_get $url, sub {
        my $content = shift;
        $cv->send(
            [ 200, [ "Content-Type" => 'text/plain', ], [$content] ] );
    };

    return sub {
        my $start_response = shift;
        $cv->cb(
            sub {
                $start_response->( shift->recv );
            }
        );
      }
  }

PSGIのHandlerでcallbackを返し、その中でhttpアクセスからの通知を待ちます(recv)。 Any::Event::http_get でレスポンスが得られたら、配列形式のレスポンスを構築しcallbackへ通知します。

起動はplackupを利用します。

% plackup --app test.psgi --server AnyEvent port 8080

アクセス先のsleep3.cgiは3秒間のsleepしてからレスポンスを返す通常のCGIです。 なので、このサーバへアクセスすると必ず、レスポンスに3秒かかります。

% time curl http://localhost:8080/
sleep 3
curl http://localhost:8080/  0.00s user 0.01s system 0% cpu 3.052 total

では、abを利用して、平行してリクエストするとどうなるでしょう。

% time ab -c 10 -n 10 http://localhost:8080/
Concurrency Level:      10
Time taken for tests:   3.328 seconds
Complete requests:      10
Failed requests:        0
Write errors:           0
Total transferred:      720 bytes
HTML transferred:       80 bytes
Requests per second:    3.01 [#/sec] (mean)
Time per request:       3327.714 [ms] (mean) 
Time per request:       332.771 [ms] (mean, across all concurrent requests)
Transfer rate:          0.21 [Kbytes/sec] received

ここで重要なのは、3行目のこのテストにあわせてどれくらいの時間がかかっているかです。
3秒×10回の30秒ではなく、ほぼ、3秒しかかかっていません。これは10個のリクエストを非同期に処理、sleep3.cgiへのアクセスし、レスポンスを返していることで実現できています。

これだけコード量も少なくこのような機能をつくれるのはうれしいですねー。

100億PVということで話題になったアメブロのMySQLの本が出たので買いました。
PVという言葉は定義によっていろいろ変るのであれですが、サーバで100億リクエストを処理していると考えるとやはり大規模なサービスであると感じます。

月間100億を秒に直すと、

10,000,000,000 / ( 3600 * 24 * 30 ) =  3,858.02469

大体4,000弱。ピークタイムではこの倍くらいになるでしょう。

本の内容は、MySQLの基本的な使い方に加えて、スケールアウトに適したアプリケーションの設計、運用に必要な監視やバックアップ、パフォーマンスチューニングについても丁寧に解説されています。
特に監視や負荷・障害対策は実際現場で経験をされた人の知識が詰まっていて良い感じです。

一つ気になったのは、MySQL 4.1、MyISAMを多く利用されているところです。 P4のコラムで触れられている

MySQLの、またInnoDBについて我々が現時点で考える問題の解消を行うには、これらの上位バージョンのMySQLに対してXtraDBの導入やGoogle v3パッチ(両方とも、本書で軽く触れています)などを適用せざるをえず、

この部分について詳しく知りたいな。

あわせて読みたい



【追記】

解決した。遅いマシンなので、fork後のsleep時間が問題だった模様。
Server::Starterは、問題を解決した0.04がでています。

http://search.cpan.org/~kazuho/Server-Starter-0.04/

Gearmanも、0.10でなおっているんだけど、

@@ -54,8 +54,8 @@ foreach my $iter (1..5) {
 }
 $tasks->wait;

-is($completed, 2, 'number of success'); # One starts immediately and on the queue
-is($failed, 3, 'number of failure'); # All the rest
+ok($completed == 2 || $completed == 1, 'number of success'); # One in the queue, plus one that may start immediately
+ok($failed == 3 || $failed== 4, 'number of failure'); # All the rest

という、「ないわー」的な対応。

実際は、t/TestGearman.pmで書かれているstart_workr後のsleepが足りない感じ。

--- 30-maxqueue.t.orig  2009-10-11 14:12:31.000000000 +0900
+++ 30-maxqueue.t       2009-10-11 14:12:50.000000000 +0900
@@ -34,6 +34,7 @@
 }

 start_worker(PORT);
+sleep 1;

 my $client = Gearman::Client->new;
 isa_ok($client, 'Gearman::Client');

これでtest通りました。

kazuhoさんのESXiでは問題でてないようなので、僕のマシンだけ遅いのは仮想マシンの設定かなぁ。。

【/追記】

VMware ESXi上のUbuntu 9.04でServer::StarterとGearmanのテストが通らなくてちょっと悩んでいる。

両方とも、テストの中で、forkを使ってサーバやworkerをたてて、それに対して親プロセスから何か操作する形なので、原因は多分同じ気がしている。
だれか解決方法を知っていたら教えてください。

エラーはこんな感じ

■Server::Starter

% prove -Ilib t/01-starter.t
t/01-starter.t .. start_server (pid:3477) starting now...
starting new worker 3478
t/01-starter.t .. 5/9 
#   Failed test 'pid should have changed'
#   at /usr/local/share/perl/5.10.0/Test/Builder.pm line 844.
#          got: '3478:hello'
#     expected: anything else
received HUP, spawning a new worker
starting new worker 3479
new worker is now running, sending TERM to old workers:3478
received TERM, sending TERM to all workers:3478,3479
worker 3478 died, status:0
worker 3479 died, status:0
exitting
# Looks like you failed 1 test of 9.
t/01-starter.t .. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/9 subtests 

Test Summary Report
-------------------
t/01-starter.t (Wstat: 256 Tests: 9 Failed: 1)
  Failed test:  9
  Non-zero exit status: 1
Files=1, Tests=9,  7 wallclock secs ( 0.03 usr  0.00 sys +  0.18 cusr  0.05 csys =  0.26 CPU)
Result: FAIL

■Gearman

[‾/develop/gearman/Gearman-1.09]% prove -Ilib t/30-maxqueue.t
t/30-maxqueue.t .. 5/6 
#   Failed test 'number of success'
#   at t/30-maxqueue.t line 58.
#          got: '1'
#     expected: '2'

#   Failed test 'number of failure'
#   at t/30-maxqueue.t line 59.
#          got: '4'
#     expected: '3'
# Looks like you failed 2 tests of 6.
t/30-maxqueue.t .. Dubious, test returned 2 (wstat 512, 0x200)
Failed 2/6 subtests 

Test Summary Report
-------------------
t/30-maxqueue.t (Wstat: 512 Tests: 6 Failed: 2)
  Failed tests:  5-6
  Non-zero exit status: 2
Files=1, Tests=6,  5 wallclock secs ( 0.02 usr  0.00 sys +  0.10 cusr  0.02 csys =  0.14 CPU)
Result: FAIL

Gearmanのテストは必ず失敗するけど、Server::Starterの方は時々成功するってのもよくわからない。