新規作成
OpenIDで認証してエントリーを新規作成します
共有
エントリーにはOpenIDで閲覧と編集に制限かけることができます
変更履歴
編集履歴もあるので、コラボレーションにも活用できます

Image::Magickの暴走対策

なんかImage::MagickがCPU100%喰って終了しなくなることがあるので、alarmで対策。

try {
    local $SIG{ALRM} = sub {
        die "error:timeout";
    };
    alarm(60);
    my $img = Image::Magick->new;
    ....
} catch {
    die $_;
} finally {
    alarm(0);
};

Try::Tiny便利

created by blog.nomadscafe.jp

test

テストです。

created by https://me.yahoo.co.jp/a/RG4e7G9JI4ZCWYAAEVkFw.pehyBjCKjzcV8-#7441c

memcachedは早くないよ。使い方によっては

memcached、memcached clientは早くても、オブジェクトのシリアライズ、デシリアライズなどを経由することで思っているよりもずっと遅くなるので注意しよう

#!/usr/bin/perl

use strict;
use warnings;
use Cache::Memcached::Fast;
use DateTime;
use Benchmark;

my $now = DateTime->now();

my $mem = Cache::Memcached::Fast->new({
    servers => [qw/localhost:11211/]
});

$mem->set( heavy => $now );
$mem->set( light => time );


Benchmark::timethese( 20000, {
    'heavy' =>  sub { $mem->get( 'heavy' ); },
    'light' => sub { $mem->get( 'light' ); },
});

上は、DateTimeオブジェクトと単なるUNIX時間(数字)を入れて、取得するのを比べてみる例

% perl test.pl
Benchmark: timing 20000 iterations of heavy, light...
     heavy:  8 wallclock secs ( 6.38 usr +  0.40 sys =  6.78 CPU) @ 2949.85/s (n=20000)
     light:  1 wallclock secs ( 0.11 usr +  0.32 sys =  0.43 CPU) @ 46511.63/s (n=20000)

1/10以下の処理スピードとなります。注目すべきは、usrのCPU。ユーザ空間のCPUもたくさん喰うのでWebアプリケーションサーバなら他の処理も結構影響を受けるよね。より大きなオブジェクトの場合はその分、時間もCPUもたくさん消費してしまうよ!

memcachedは早いはずという考えて、1ページを生成する間に同じkeyをなんども取得してしまう事があるかもしれないけど、そこは一度アプリケーションのプロセスでキャッシュするなどの対策を考えよう


(memcahcedの仕組みを知るためのエントリーです。シリアライザーの速度に関するエントリーではありません)

created by blog.nomadscafe.jp

LIMILICで作成

Test

created by http://www.hatena.ne.jp/tom_k-0710/

mogilefsのような分散Webストレージを妄想ちう(メモです)

思うところがあって、シンプルでスケーラブルな分散Webストレージを考え中。

メモなのでまとまってません。ノード周りはmixiのインスパイア


ターゲットしてはファイル数が億単位になっても大丈夫なぐらいを目指す


いくつか機能としては

  • MySQLに分散情報、メタデータを持つ。
  • bucketという単位を持つ。bucketごと削除が可能かも。ジョブキューが必須
  • ファイルは3台(ハードコード)のノードにコピーする
  • ノードは3台一組。壊れたら同じ組のノードからコピーして復旧する
  • ファイルの保存時に、1台のノードでも保存ができなかったら、別の組に変更する。書いてしまった分はジョブキュー経由で削除
  • ファイルのアップロードはwebdavみたいなインターフェイスで

外部のURL構造は、

http://ws.foo.com/{bucket_name}/{filename}

とし、内部的には

http://node:port/{00}/{00}/{00}/{bucket_id}_{filename_id}

とする。

この際、{filename_id}は、tmaesakaのDigest::MurmurHashを使って32bit uintとなる。

1つのbucketにマジ大量のファイルを置かなければ衝突する可能性はそれなり低い。。はず。

{00}/{00}/{00} はfilename_idの下6桁から生成で。


bucket_idはauto_incrementで付加する。


この様な仕組みを持つと、元のファイル名をかなり小さい容量に圧縮ができ、また計算で求められるため、元のファイル名から内部ファイル名への変換テーブルを持たなくて済む。つまりメタデータのDBを小さくできる。


元のファイル名や付加情報は、コンテンツのヘッダに埋め込む

file content = [length(2byte)][{json data}][data..]
json = {
  ct: 'image/jpeg',
  fn: 'original_filename.jpg'
}

JSONでシリアライズして、長さと一緒に保存しちゃう。


ここまでで、MySQLのスキーマを考えてみると

CREATE TABLE nodes (
    id INT UNSINGED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    gid SMALLINT UNSINGED NOT NULL,
    node varchar(64),
    can_read TINYINT UNSIGNED DEFAULT 0,
    is_fresh TINYINT UNSIGNED DEFAULT 0
) ENGINE=InnoDB;

#id, gid, node,              can_read, is_fresh
#1,  1,  '192.168.55.10:80', 1,        1
#2,  1,  '192.168.55.11:80', 1,        1
#3,  1,  '192.168.55.12:80', 1,        1
#4,  2,  '192.168.55.13:80', 1,        1
#5,  2,  '192.168.55.14:80', 1,        1
#6,  2,  '192.168.55.15:80', 1,        1


CREATE TABLE buckets (
    id INT UNSINGED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(32) UNIQUE,
    enable TINYINT UNSINGED DEFAULT 1, --# 一時停止
    delete TINYINT UNSINGED DEFAULT 0, --# 完全削除
) ENGINE=InnoDB

#id, name,        enable, delete
#1,  'kazeburo',  1,      1
#2,  'chibiburo', 1,      1
#3,  '_system',   1,      1


CREATE TABLE objects (
    fid INT UNSINGED NOT NULL, --# filename_id, murmurhash(filename)
    bucket_id INT UNSINGED NOT NULL,
    gid SMALLINT UNSINGED NOT NULL,
    PRIMARY KEY(ckey, bucket_id),
    INDEX (bucket_id)
) ENGINE=InnoDB;

#fid,         bucket_id, gid
#1173386060, 1,         1     #http://ws.foo.com/kazeburo/greatphoto.jpg => node 1,2,3
#3157638903, 2,         1     #http://ws.foo.com/chibiburo/myphoto.jpg   =>  node 1,2,3
#1357344895, 1,         2     #http://ws.foo.com/kazeburo/new.jpg   =>  node 4,5,6

な感じ。


objectsテーブルは、1行のデータサイズが10byteと小さいので、億単位のrowを入れてもなんとかなるんじゃないかと思う。


(object テーブルを変更しました 2010/07/30)

created by blog.nomadscafe.jp

shell scriptでportが閉じるまで待つ

ncの-zオプションが使える

while nc -z localhost 11211 > /dev/null 2>&1;
do
  echo 'wait for exit'
  sleep 1
done
echo 'exited'
created by blog.nomadscafe.jp

Gearman::XS試し中

workerでdieするときの動作


worker


#!/usr/bin/perl

use strict;
use warnings;
use Gearman::XS qw(:constants);
use Gearman::XS::Worker;

my $worker = Gearman::XS::Worker->new;
$worker->add_server("127.0.0.1", 4730);

$worker->add_function(
    "reverse",
    0,
    sub { die shift->workload() },
    {}
);

while(1){
    warn "work start";
    my $ret = $worker->work();
    warn "return: $ret";
    warn "error:" . $worker->error();
    warn "work end";
}

client

% echo foo |  gearman -t 1000 -h 127.0.0.1 -p 4730 -f reverse
Job failed

worker log

work start at testworker.pl line 20.
Job: 'reverse' died with: foo at testworker.pl line 14.
return: 0 at testworker.pl line 22.
error:gearman_wait:timeout reached at testworker.pl line 23.
work end at testworker.pl line 24.
work start at testworker.pl line 2

dieしてもworkの戻り値は0=成功。

errorの内容をみないとわからない


けど、dieしなくてもerrorに

error:gearman_wait:timeout reached at testworker.pl line 23.

とかでたりもするし、dieしてもtimeoutでたり、何もでなかったり。


何この謎仕様

created by blog.nomadscafe.jp

__DIR__

package DIR;

use strict;
use warnings;
use base qw/Exporter/;
use Cwd qw/realpath/;
use File::Basename qw/dirname/;

our @EXPORT = qw/__DIR__ __RDIR__ __RFILE__/;

sub __DIR__ () {
    dirname( (caller)[1] );
}

sub __RDIR__ () {
    dirname( realpath( (caller)[1] ));
}

sub __RFILE__ () {
    realpath( (caller)[1] );
}

1;
created by blog.nomadscafe.jp

Memcachedの起動パラメータをSNMP経由で取得する

statsで調べることができないmax connectionとか調べたいときに


まず、PIDを調べる。PIDはstatsでとれる

% telnet 192.168.x.x 11211
Trying 192.168.x.x...
Connected to xxx (192.168.x.x).
Escape character is '^]'.
stats
STAT pid 27060 **ココ
STAT uptime 6128543
STAT time 1278056399
(略)

SNMPで起動パラメータがとれる

snmpwalk -c DataHotel -v 2c 192.168.x.x hrSWRunParameters.[pid]
HOST-RESOURCES-MIB::hrSWRunParameters.27060 = STRING: "-m 64 -c 1024 -u memcached -p 12345"
created by blog.nomadscafe.jp

SNMPでCPU数

HOST-RESOURCES-MIBいろいろとれるね

http://www.oidview.com/mibs/0/HOST-RESOURCES-MIB.html

% snmpwalk -v 2c -c public localhost hrDeviceType|grep hrDeviceProcessor
HOST-RESOURCES-MIB::hrDeviceType.768 = OID: HOST-RESOURCES-TYPES::hrDeviceProcessor
HOST-RESOURCES-MIB::hrDeviceType.769 = OID: HOST-RESOURCES-TYPES::hrDeviceProcessor

CPUの詳細は

% snmpwalk -v 2c -c public localhost hrDeviceDescr
HOST-RESOURCES-MIB::hrDeviceDescr.768 = STRING: AuthenticAMD: Quad-Core AMD Opteron(tm) Processor 1354
HOST-RESOURCES-MIB::hrDeviceDescr.769 = STRING: AuthenticAMD: Quad-Core AMD Opteron(tm) Processor 1354
created by blog.nomadscafe.jp

<12345678910>