和三年前的博客一样,还是时间加密钥加路径的加密方式。不过这次改用nginx,这样不用重新缓存后面的squid文件了。 先用ngx_lua做:

    set $expire "600";
    set $salt "mysalt";
    location ~* \.mp3$ {
#local m = ngx.re.match(ngx.var.uri,"^/([0-9]{4})/([0-9]{2})/([0-9]{2})/([0-9]{2})/([0-9]{2})/([0-9a-z]{32})(/.*)")
#用ngx.re.match就不能%d,用string.match就不能{2},郁闷
#而且ngx.re.match所有的捕获都在m数组里,这点类似perl的m//返回。
        rewrite_by_lua '
        local date = {}
        local md5str
        local path
        date.year,date.month,date.day,date.hour,date.min,md5str,path = string.match(ngx.var.uri,"^/(%d+)/(%d+)/(%d+)/(%d+)/(%d+)/(%w+)(/%S+)")

        if date.year == nil then
             ngx.exit(404)
        end

        local time1 = tonumber(os.time(date))
        local time2 = tonumber(ngx.time())
        if md5str == ngx.md5(ngx.var.salt..date.year..date.month..date.day..date.hour..date.min..path) then
            if time2 - time1 < tonumber(ngx.var.expire) then
                ngx.req.set_uri(path)
            else
                ngx.exit(405)
            end
        else
            ngx.exit(403)
        end
        ';  
        proxy_pass         http://backend;
        proxy_set_header   Host     $host;
    }

然后用nginx_perl做:

    perl_require POSIX.pm;
    perl_require Digest/MD5.pm;
    perl_set $realurl '
    sub {
        my $secret = "mysalt";
        my $expire = 600;
        my $r = shift;
        if ( $r->uri =~ m#^/(\d{4})/(\d{2})/(\d{2})/(\d{2})/(\d{2})/(\w{32})(/\S+\.mp3)#oi ) {
            my ($year, $mon, $mday, $hour, $min, $md5, $path) = ($1, $2, $3, $4, $5, $6, $7);
            my $str = Digest::MD5::md5_hex($secret . $year . $mon . $mday . $hour . $min . $path);
            my $reqtime = POSIX::mktime(00, $min, $hour, $mday, $mon - 1, $year - 1900);
            my $now = time;
            if ( $str eq $md5 and $now - $reqtime < $expire ) {
                    return $path;
            } else {
                return "error";
            };
        } else {
            return "error";
        };
    }';
   
  server { 
    location ~* \.mp3$ {
                if ($realurl = "error") { return 403; }
                proxy_pass         http://music_store_local$realurl;
                proxy_set_header   Host             $host;
    }
  }

然后用http_load测试单url响应情况,基本效率一样。在压力比较大(lo上跑大概200MB/s,再大就可能出错了)的情况下,第一字节响应时间大概比直接请求squid多一个数量级(从0.4ms到4ms)
这个情况下,squid的cpu%在130%,nginx_perl的worker是25%,nginx_lua的是19%。