极路由内网缓存服务器插件开发过程

参考资料

思路

设备选用极1s

给极路由插上SD卡,使用SD卡放缓存(注:插上SD卡后,SD卡在极路由上的目录为:/tmp/storage/mmcblk0 )。

首先手动配置以测试方法正确性,然后再写插件包。

STEP1: 配置

修改nginx配置文件:

vi /etc/nginx/nginx.conf

在http段添加:

proxy_cache_path /tmp/storage/mmcblk0/proxy_cache levels=1:2 keys_zone=hiwifi_cache:10m inactive=1d max_size=2g;
proxy_temp_path /tmp/storage/mmcblk0/proxy_tmp;

在http段内增加一个server段:

server {
    listen 13128;
	resolver 180.76.76.76 223.5.5.5 223.6.6.6 114.114.114.114;
	proxy_cache hiwifi_cache;
	proxy_max_temp_file_size 100m;
	proxy_cache_valid  200 302 304 24h;
	location / {
		proxy_pass http://$host$request_uri;
		proxy_connect_timeout   60;
		proxy_send_timeout     60;
		proxy_read_timeout     60;
	}
    location ~ .*\.(php|jsp|cgi|asp)?$ {
        proxy_pass http://$host$request_uri;
    }
}

配置iptables:

iptables -t nat -A PREROUTING -i br-lan -p tcp  --dport 80 -j REDIRECT --to-ports 13128

重启nginx:

nginx -s reload

STEP2: 测试

电脑打开 http://im.qq.com/download/ ,下载PC版,50多M的文件。下的时候看一下网速,下完之后再下一次,对比一下网速。

我第一次是1M多一秒,第二次是11M多一秒,显然测试成功。

STEP3: 写插件

这里有三个文件:script、manifest.json、vh.cache_server_by_yumi.conf

最后那个是给nginx用的。以vh.开头是因为nginx.conf里面include了vh.*.conf,虽然不知道那堆官方文件是干啥用的。

下面是最初(版本1.0.0)的代码。

script

#!/bin/sh

install()
{
    # 拷贝nginx缓存配置
    cp ./vh.cache_server_by_yumi.conf /etc/nginx/
    # 重新加载nginx配置
    nginx -s reload
    # 启动
    start
}

uninstall()
{
    # 卸载之前先停止运行
    stop
    # 删除nginx缓存配置
    rm /etc/nginx/vh.cache_server_by_yumi.conf
    # 重新加载nginx配置
    nginx -s reload
    # 清空缓存
    rm -rf /tmp/storage/mmcblk0/cache_server_cache
    rm -rf /tmp/storage/mmcblk0/cache_server_temp
}

start()
{
    iptables -t nat -I PREROUTING 1 -i br-lan -p tcp  --dport 80 -j REDIRECT --to-ports 13128
}

stop()
{
    iptables -t nat -D PREROUTING 1
    # 非必需。出现某些bug时使用这个可能有效。
    nginx -s reload
}

status()
{
    iptables_var1=$(iptables -t nat -L PREROUTING)
    iptables_var2=$(echo "$iptables_var1"|grep 13128)
    if [ -n "$iptables_var2" ]
    then
        echo "{ \"status\" : \"running\" }"
    else
        echo "{ \"status\" : \"stopped\" }"
    fi
}

manifest.json

{
"manifest_version": "2.0.0",
"supportgetappstatus": 1
}

vh.cache_server_by_yumi.conf

proxy_cache_path /tmp/storage/mmcblk0/cache_server_cache keys_zone=cache_server_by_yumi:2m inactive=12h max_size=2g;
proxy_temp_path /tmp/storage/mmcblk0/cache_server_temp;

server {
    listen 13128;
    resolver 180.76.76.76 223.5.5.5 223.6.6.6 114.114.114.114;
    #proxy_max_temp_file_size 1m;
    #proxy_buffer_size 4k;
    #proxy_buffers 4 32k;
    #proxy_busy_buffers_size 64k;
    #proxy_temp_file_write_size 64k;
    proxy_cache_key "$host$request_uri";
    # 下面是缓存部分
    location ~* \.(html|htm|css|js|xml|xhtml|jpg|gif|ico|png|jpeg|psd|wav|mp3|mp4|avi|rvmb|flv|swf|exe|apk|zip|rar|7z|tar|xz|gz|tgz|bz|img|iso)$ {
        proxy_pass http://$host$request_uri;
        proxy_cache cache_server_by_yumi;
        proxy_cache_valid  200 12h;
    }
    # 其它不缓存
    location / {
        proxy_pass http://$host$request_uri;
    }
}

下面是版本1.1.6的代码。

script

#!/bin/sh

# TODO:修改正则表达式

install()
{
    # 备份配置以便在status中读取
    cp ./CacheServer.conf /tmp/storage/mmcblk0/
    # 读取配置
    . CacheServer.conf
    # 修改参数
    sed -i "s/inactive=[0-9]*h/inactive="$cachetime"h/g" ./vh.cache_server_by_yumi.conf
    sed -i "s/max_size=[0-9]*g/max_size="$cachespace"g/g" ./vh.cache_server_by_yumi.conf
    sed -i "s/proxy_cache_valid  200 [0-9]*h/proxy_cache_valid  200 "$cachetime"h/g" ./vh.cache_server_by_yumi.conf
    # 拷贝nginx缓存配置
    cp ./vh.cache_server_by_yumi.conf /etc/nginx/
    # 重新加载nginx配置
    nginx -s reload
    # 给日志加点内容以免刚安装时状态显示“未知”
    echo "200 0 MISS">/tmp/storage/mmcblk0/cache_server.log
    # 启动
    start
}

uninstall()
{
    # 删除nginx缓存配置
    rm /etc/nginx/vh.cache_server_by_yumi.conf
    # 停止运行并重新加载nginx配置
    stop
    # 清空缓存
    rm -rf /tmp/storage/mmcblk0/cache_server_cache
    rm -rf /tmp/storage/mmcblk0/cache_server_temp
    # 删除备份配置和日志
    rm -rf /tmp/storage/mmcblk0/CacheServer.conf
    rm -rf /tmp/storage/mmcblk0/cache_server.log
}

start()
{
    iptables -t nat -I PREROUTING 1 -i br-lan -p tcp  --dport 80 -j REDIRECT --to-ports 13128
}

stop()
{
    iptables -t nat -D PREROUTING 1
    # 非必需。出现某些bug时使用这个可能有效。
    nginx -s reload
}

status()
{
    # 读取备份的配置
    . /tmp/storage/mmcblk0/CacheServer.conf
    # 检查使用的空间大小
    space_usage_var1=$(du /tmp/storage/mmcblk0/cache_server_cache/)
    space_usage_var2=$(echo $space_usage_var1|cut -d " " -f 1)
    let space_usage_var3=$space_usage_var2/1024
    let avilable_space=$cachespace*1024
    # 统计缓存条目个数
    item_number=$(ls -lR /tmp/storage/mmcblk0/cache_server_cache/|grep "^-"|wc -l)
    # 计算命中率
    hit_rate_var1=$(grep -c '' /tmp/storage/mmcblk0/cache_server.log) # 总请求数目
    hit_rate_var2=$(grep -c 'HIT' /tmp/storage/mmcblk0/cache_server.log) # 缓存命中数目
    hit_rate_var3=$(awk 'BEGIN{print '$hit_rate_var2'/'$hit_rate_var1'*100 }') # 缓存命中率
    # 计算节省的流量
    traffic_saved_var1=$(grep 'HIT' /tmp/storage/mmcblk0/cache_server.log|awk 'BEGIN{sum=0}{sum+=$1}END{print sum}')
    traffic_saved_var2=$(awk 'BEGIN{print '$traffic_saved_var1'/1024/1024 }')
    # 获取CPU负载
    cpu_load_var1=$(uptime|cut -d ":" -f 5) # 改!BUG:一天后无法获取
    #cpu_load_var1=$(uptime|cut -d " " -f 9|cut -d "," -f 1) # 1min负载
    # 检查iptables
    iptables_var1=$(iptables -t nat -L PREROUTING)
    iptables_var2=$(echo "$iptables_var1"|grep 13128)
    if [ -n "$iptables_var2" ]
    then
        echo '{ "status" : "running", "msg" : "最长缓存时间:'$cachetime'h</br>缓存条目数量:'$item_number'条</br>已用缓存空间:'$space_usage_var3'M/'$avilable_space'M</br>缓存命中率:'$hit_rate_var3'%</br>节省的流量:'$traffic_saved_var2'M</br>服务器负载:'$cpu_load_var1'" }'
    else
        echo '{ "status" : "stopped", "msg" : "最长缓存时间:'$cachetime'h</br>缓存条目数量:'$item_number'条</br>已用缓存空间:'$space_usage_var3'M/'$avilable_space'M</br>缓存命中率:'$hit_rate_var3'%</br>节省的流量:'$traffic_saved_var2'M</br>服务器负载:'$cpu_load_var1'" }'
    fi
}

reconfigure()
{
    cp ./CacheServer.conf /tmp/storage/mmcblk0/
    . CacheServer.conf
    sed -i "s/inactive=[0-9]*h/inactive="$cachetime"h/g" /etc/nginx/vh.cache_server_by_yumi.conf
    sed -i "s/max_size=[0-9]*g/max_size="$cachespace"g/g" /etc/nginx/vh.cache_server_by_yumi.conf
    sed -i "s/proxy_cache_valid  200 [0-9]*h/proxy_cache_valid  200 "$cachetime"h/g" /etc/nginx/vh.cache_server_by_yumi.conf
    nginx -s reload
}

manifest.json

{
    "manifest_version": "2.0.0",
    "supportgetappstatus": 1,
    "requirements": {
        "support_refconfig":1
    },
    "configuration": [
        {
            "name": "缓存空间",
            "type": "text",
            "variable": "cachespace",
            "defaultvalue": "4",
            "required": 1,
            "description": "单位:GB",
            "regexpression": "^[0-9]*$"
        },
        {
            "name": "缓存时间",
            "type": "text",
            "variable": "cachetime",
            "defaultvalue": "72",
            "required": 1,
            "description": "单位:小时",
            "regexpression": "^[0-9]*$"
        }
    ]
}

vh.cache_server_by_yumi.conf

proxy_cache_path /tmp/storage/mmcblk0/cache_server_cache keys_zone=cache_server_by_yumi:1m inactive=72h max_size=4g; # 1m大约能存储8150-8200条key,总文件大小约2G。以后更新:根据缓存空间修改key缓存大小。
proxy_temp_path /tmp/storage/mmcblk0/cache_server_temp;
log_format cache '$body_bytes_sent $upstream_cache_status';
server {
    listen 13128;
    resolver 180.76.76.76 223.5.5.5 223.6.6.6 114.114.114.114;# 以后更新:允许自定义DNS或者自动获取DNS
    proxy_cache_key "$host$request_uri";
    # 下面是缓存部分 以后更新:允许自定义缓存的文件
    location ~* \.(html|htm|css|js|xml|xhtml|jpg|jpeg|gif|png|ico|bmp|tiff|raw|ai|psd|wav|mp3|wma|midi|mid|ogg|flac|aac|mp4|avi|rvmb|rm|mov|3gp|mkv|f4v|flv|swf|exe|apk|zip|rar|7z|tar|xz|gz|tgz|bz|cab|jar|img|iso|pdf|doc|docx|xls|xlsx|ppt|pptx|txt)$ {
        proxy_pass http://$host$request_uri;
        proxy_cache cache_server_by_yumi;
        proxy_cache_valid 200 72h;
        add_header HiWiFi-Cache "$upstream_cache_status";
        access_log /tmp/storage/mmcblk0/cache_server.log cache;
    }
    # 其它不缓存
    location / {
        proxy_pass http://$host$request_uri;
    }
}