« 2007年07月 | メイン | 2007年09月 »

2007年08月31日

LVS/TUN without iptables

IP tunnelingを利用したLVSで、VIPをリアルサーバで処理するために、iptablesを使ってましたが、iptablesのip_conntrack_max(nf_conntrack_max)とかが気になる(気になる程度、限界はわからない)なので、iptablesを使わない方法を調べてみました

iptablesを使ったパターンでは、redirectを使います。
tunl0にethXのIPを割り当てて起動し、VIP宛のパケットを受け取る設定になります

IF0=`/sbin/ifconfig eth0 | grep 'inet addr:' | awk {'print $2'} | head -1 | cut -d ':' -f 2`
/sbin/ifconfig tunl0 $IF1 netmask 255.255.255.255 up
/sbin/iptables -t nat -A PREROUTING -d $VIP -j REDIRECT


iptableを使わない場合、Kernel 2.6.5以降では、arpリクエストへの変更をkernelパラメータのarp_ignoreとarp_annunceで設定できますので、こちらを使います。
この場合、tunl0にはVIPを割り当てます。

VIP=192.168.1.1
/sbin/ifconfig tunl0 $VIP netmask 255.255.255.255 broadcast $VIP up
echo 1 > /proc/sys/net/ipv4/conf/tunl0/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/tunl0/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce


arp_ignoreとarp_announceについての解説
http://kb.linuxvirtualserver.org/wiki/Using_arp_announce/arp_ignore_to_disable_ARP

LVS/TUNではなく、DSRの場合は
http://request-timeout.net/%E8%B2%A0%E8%8D%B7%E5%88%86%E6%95%A3/lvs

2007年08月27日

WebService::TimeLine公開しました

かなり以前のことですが、某縁があって7/30,31とniftyさんの開発合宿に参加させて頂きました。
完全に外野からの参加でしたが、いくつかの会社の方が参加していて、普段とは違う刺激になりました。Ruby&Macが多かった。

んで、結局できたものは、サービスの形ではなく、@nifty TimeLineのPerlのモジュールとサンプル

モジュールはCPANに先々週にアップしています
WebService::TimeLine

TimeLineは、時間軸と自由に設定可能な縦軸を持った年表作成サービスで、ソーシャル機能とかも持っています。個人的には、Flashのインターフェイスがとてもいい感じです。
しかも、APIが付いた事でいろいろなデータを自動で追加していける可能性がでてきたので、面白いんじゃないかなーと思ってます。

とりあえず、サンプル的に作ったのは、Gooの地震情報RSSを取得し、API経由でTimeLineにデータを流し込む、地震速報タイムラインです。


(公開した時に既に同じ事をやっている方がいてハゲシクorz)
あと、合宿中にミクシィのあしあとタイムラインもつくってみたけど、こちらは公開はしてなかったりします。

以下、地震情報の取得と登録のプログラムのソース(簡略化版)
フルのコードはこちら

#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use XML::RSS::Liberal;
use DateTime;
use DateTime::Format::W3CDTF;
use Data::Visitor::Encode;
use WebService::TimeLine;

my $ua = LWP::UserAgent->new;
my $res = $ua->get('http://weather.goo.ne.jp/earthquake/index.rdf');
my $rss = XML::RSS::Liberal->new;
$rss->parse($res->content);

my $dev = Data::Visitor::Encode->new();
my $tl = WebService::TimeLine->new( timeline_key => '*************************' );

foreach my $item (@{ $rss->{items} }) {
    use utf8;
    my $re = '^\[震源地\]\s*(.+)\s*\[最大震度\]\s*震度(\d+)\s*((\d{4})年(\d+)月(\d+)日\s*(\d+)時(\d+)分頃発生';
    if ( $item->{title} =~ m!$re! ) {
        my $epicenter = $1;
        my $intensity = $2;
        my $dt = DateTime->new(
            year  => $3, month => $4, day   => $5, hour  => $6,
            minute => $7, second => 0, time_zone => 'Asia/Tokyo',
        );
        if ( $content =~ /北緯(\d+\.\d+)度\s*東経(\d+\.\d+)度/ ) {
            my $nl = $1;
            my $el = $2;
        }
        $res = $tl->create_article(@{
            $dev->utf8_off([
                timeline_id  => 2940,
                title       => "$epicenter 最大震度$intensity",
                description => "$epicenter 最大震度$intensity " . "$dt",
                start_time  => DateTime::Format::W3CDTF->format_datetime($dt),
                end_time    => DateTime::Format::W3CDTF->format_datetime($dt),
                grade       => $intensity,
                link        => $item->{link},
            ])
        }) or die $tl->errstr;
    }
}


もごもごと、これでWeb API系のモジュールを2つ連続して作った訳ですが、Net::Twitterを少し拡張しただけのWebService::Mogo2と比べて、TimeLineの野良XML APIは非常に面倒。APIを提供していく側はJSONやYAML、あるいはAtompubを採用していくとAPIを利用する開発者は新しいインターフェイスモジュールを用意しなくてもよくなるので、マッシュアップとかハックも楽になるんじゃないかなぁと思いました。

2007年08月24日

GearmanとかNginxとか

ひさびさにFemoを弄った。
サーバ周りを中心にいくつか改善

まず、以前FastCGIの環境で動かないと書いたText::VimColorGearmanを使うようにしてみました。
Text::VimColorはText::Hatena(バージョン0.16)の中で使われています

#Worker(worker.pl)

my $worker = Gearman::Worker->new;
$worker->job_servers(qw/127.0.0.1/);

$worker->register_function(
    vimcolor_html => sub {
        my $g = shift;
        my $arg = Storable::thaw( $g->arg );
        my %arg = map { $_ => $arg->{$_} } grep { $_ !~ /^(file|vim_command|vim_options|vim_let)$/ } keys %$arg;
        my $syntax = Text::VimColor->new(%arg);
        return $syntax->html;
    }
);

$worker->work() while 1;


#Text::Hatena::SuperpreNodeを上書き

use Gearman::Client;
use Storable;
sub Text::Hatena::SuperpreNode::format_vimcolor {
    my $self = shift;
    my $s = shift;
    $self->{syntax_type} = $self->{syntax_type} eq '?' ?
        '' : $self->{syntax_type};
    my $client = Gearman::Client->new;
    $client->job_servers( '127.0.0.1' );
    my $result_ref = $client->do_task(
        'vimcolor_html',
        Storable::freeze( { 
            string => $s,
            filetype => $self->{syntax_type},
        } )
    );
    return unless $result_ref;
        $$result_ref;
}


workerとgearmandはdaemontoolsで起動してます

#gearmand起動スクリプト

#!/bin/sh
exec 2>&1
exec setuidgid apache /usr/bin/gearmand


#worker起動スクリプト

#!/bin/sh
exec 2>&1
exec /path/to/Femo/script/vimcolor_worker.pl


こうすると、workerの再起動が、

svc -t /service/worker

で可能になるので、変更の適用がすごく楽になります
万が一プロセスが落ちても、すぐに復帰してくれるのも利点です


これでFastCGIでも動作ができるようになったので、Apacheのmod_perlからNginxのFastCGIへ変更しました
FastCGIのプロセスもdaemontoolsで起動します

#fastcgi起動スクリプト

#!/bin/sh
exec 2>&1
exec /path/to/Femo/script/femo_fastcgi.pl -l 127.0.0.1:9001 -p /var/run/femo_fastcgi.pid -n 3


あとはNginxの設定になります。NginxでCatalystを動かすドキュメントは本家のWikiにもあります。

FastCGIに渡す、パラメータのConfigファイル(nginx_fastcgi_params.conf)

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx;

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  PATH_INFO          $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

fastcgi_param REDIRECT_STATUS 200;


Nginxの設定 nginx.conf

http {
    gzip             on;
    server {
        listen 80;
        server_name femo.jp;

        location / {
            fastcgi_pass 127.0.0.1:9001;
            include      /path/to/conf/nginx_fastcgi_params.conf;
        }
        location /static {
            alias /path/to/Femo/root/static;
            expires  31d;
        }
    }
}


全部起動して、設定完了です
パフォーマンスとか全然はかってないけど、なんかモダンになった気がします

workerの危険なオプションを取り除く正規表現を間違えて3〜4時間悩んでいたのは秘密

2007年08月10日

軽量 Web サーバー

IBM 軽量 Web サーバー - Japan」にnginxがない件
やはり英語圏では弱いんだろうな。

画像サーバなどで、nginxを使い始めてます。