用perl给nginx写个IP地址查找模块

2010-12-26

perl怎么给nginx写模块,其实并不难。网上 search 一下很多 如何安装和配置,参考官方文档: http://wiki.nginx.org/EmbeddedPerlModule

nginx配置:

worker_processes  1;
error_log  logs/error.log  info;
events {
    worker_connections  1024;
}
http {
    perl_modules  /opt/perl/lib/;
    perl_require  IPaddr.pm;

    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            perl  IPaddr::handler;
        }
    }
}

模块主要功能:

request 提交一个 IP 地址 www.nginx.com/?8.8.8.8 返回用户这个IP 地区

性能:

不搭载nginx 跑了下 查找一个IP 消耗 20ms 速度并不快(不统计预编译时间)。 搭载nginx 测试了下

time curl   http://192.168.1.103/?211.151.63.100
北京市
real    0m0.135s
user    0m0.004s
sys     0m0.008s

优化计划:

精简IP 地址库标 算法优化 性能提升10倍以上

源代码如下:

package IPaddr;
BEGIN {
    open my $fh, "<./ip.list" or die "$!\n";
    our %ip;
    our @nums;
    while(<$fh>)
    {
        my ($a,$b) = split /\s+/;
        push @nums, $a;
        $ip{$a} = $b;
    }
    close $fh;
    @nums = sort {$b <=> $a} @nums;
}

use nginx;
use Socket;

sub handler {
    $r = shift;
    $r->send_http_header('Content-Type', 'text/html; charset=utf-8');
    return OK if $r->header_only;
    my $city;
    my $num = unpack "N4", inet_aton($r->args);
    my $index = $#num / 2;
    if ( $num <= $nums[$index])
    {
        for (@nums[$index..$#nums])
        {
            $city = $ip{$_} and last if $num >= $_;
        }
    }
    else
    {
        for (@nums[0..$index])
        {
            $city = $ip{$_} and last if $num >= $_;
        }
    }
    $r->print("$city");
    $r->rflush();
}
1;