Nginx一键清除域名下Cache

装载请注明出处:http://www.firefoxbug.com/?p=1985
在前面一篇文章 http://www.firefoxbug.com/?p=1861 已经介绍如何把站点缓存分域名存放。相比之前的purge一个个URL刷新,按照域名存放对于站点Cache一键刷新是很方便的。本文会介绍如何通过开发一个Nginx三方模块,一键刷新某个域名站点下缓存。 注意:在使用下面模块之前必须根据前文,站点Cache已经按照目录存储,目录在 /home/cache/下。比如 www.firefoxbug.net 的 Cache 是 /home/cache/www.firefoxbug.net/ ,通过模块能一键清除此目录cache。

定义模块

ngx_module_t  ngx_http_move_domain_cache_module = {
    NGX_MODULE_V1,
    &ngx_http_move_domain_cache_module_ctx,              /* module context */
    ngx_http_move_domain_cache_commands,                 /* module directives */
    NGX_HTTP_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,             /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,             /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};

定义模块上下文

static ngx_http_module_t  ngx_http_move_domain_cache_module_ctx = {
    NULL,                                  /* preconfiguration */
    NULL,                                     /* postconfiguration */
    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */
    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */
    NULL,                                  /* create location configuration */
    NULL                                   /* merge location configuration */
};

定义模块指令

/* Commands */
static ngx_command_t  ngx_http_move_domain_cache_commands[] = {
    { ngx_string("mv_cache"),
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
      ngx_http_move_domain_cache,
      0,
      0,
      NULL },
    ngx_null_command
};

定义模块指令回调函数

static char *
ngx_http_move_domain_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf ;
    /* register hanlder */
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_move_domain_cache_handler;
    return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_move_domain_cache_handler(ngx_http_request_t *r)
{
    ngx_buf_t    *b;
    ngx_chain_t   out;
    ngx_str_t domain;
    u_char *cache_path;
    ngx_int_t path_len ;

    domain.data = r->headers_in.server.data;
    domain.len = ngx_strlen(domain.data);

    cache_path = ngx_pcalloc(r->pool,domain.len + sizeof(ngx_domain_cache_path));
    path_len = ngx_strlen(ngx_domain_cache_path);
    ngx_memcpy(cache_path,ngx_domain_cache_path,path_len);
    ngx_memcpy(&cache_path[path_len],domain.data,domain.len);

    /* Http Output Buffer */
    if (ngx_delete_cache_dir((char *)cache_path,r) == NGX_FILE_ERROR) {
        /* entry in error log is enough, don't notice client */
        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                      ngx_delete_file_n " \"%s\" failed", cache_path);
    }

    r->headers_out.content_type.len = sizeof("text/html") - 1;
    r->headers_out.content_type.data = (u_char *) "text/html";
    //why not malloc memory from stack
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

    out.buf = b;
    out.next = NULL;

    b->pos = cache_path;
    b->last = domain.data + domain.len + sizeof(ngx_domain_cache_path);

    b->memory = 1;
    b->last_buf = 1;

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = domain.len + sizeof(ngx_domain_cache_path);

    ngx_http_send_header(r);

    return ngx_http_output_filter(r, &out);
}

删除cache目录

static ngx_int_t
ngx_is_path_dir(char * filename)
{
        struct stat buf;
        ngx_int_t ret = stat(filename,&buf);
        if(0 == ret)
        {
            if(buf.st_mode & S_IFDIR)
            {
                    return 0;
            }
            else
            {
                    return 1;
            }
        }
        return -1;
}

static ngx_int_t
ngx_delete_cache_dir(char * dirname,ngx_http_request_t *r)
{
        char *chBuf;
        DIR * dir = NULL;
        struct dirent *ptr;
        ngx_int_t ret = 0;

        dir = opendir(dirname);
        if(NULL == dir)
        {
            return -1;
        }

        chBuf = ngx_pcalloc(r->pool,256);
        while((ptr = readdir(dir)) != NULL)
        {
                ret = strcmp(ptr->d_name, ".");
                if(0 == ret)
                {
                        continue;
                }

                ret = strcmp(ptr->d_name, "..");
                if(0 == ret)
                {
                    continue;
                }

                snprintf(chBuf, 256, "%s/%s", dirname, ptr->d_name);
                ret = ngx_is_path_dir(chBuf);
                if(0 == ret)
                {
                    ret = ngx_delete_cache_dir(chBuf,r);
                    if(0 != ret)
                    {
                            return -1;
                    }
                }
                else if(1 == ret)
                {
                    ret = remove(chBuf);
                    if(0 != ret)
                    {
                        return -1;
                    }
                }
        }
    (void)closedir(dir);

    ret = remove(dirname);
    if(0 != ret)
    {
        return -1;
    }
    return 0;
}

模块编译

1. mkdir /opt/nginx_move_domain_cache/
2. vim /opt/nginx_move_domain_cache/config 
ngx_addon_name=ngx_http_move_domain_cache_module
HTTP_MODULES="$HTTP_MODULES ngx_http_move_domain_cache_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_move_domain_cache_module.c"
CORE_LIBS="$CORE_LIBS -lpcre"
3. vim /opt/nginx_move_domain_cache/ngx_http_move_domain_cache_module.c
4. wget http://tengine.taobao.org/download/tengine-1.4.6.tar.gz
5. tar -zxvf tengine-1.4.6.tar.gz
6. cd tengine-1.4.6
7. ./configure --prefix=/usr/local/nginx --add-module=/opt/nginx_move_domain_cache/
8. make && make install

配置文件编写 1. vim /usr/local/nginx/conf/nginx.conf

server {
        listen 80;
        server_name www.firefoxbug.net;
        gzip on;

        location /mv_cache{
                mv_cache;
        }
        ....
}

ngx_http_move_domain_cache_module.c完整源码

#include <ngx_config.h>  
#include <ngx_core.h>  
#include <ngx_http.h>  
#include <sys/stat.h>
#include <dirent.h>
  
static char *ngx_http_move_domain_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_delete_cache_dir(char * dirname,ngx_http_request_t *r);
static ngx_int_t ngx_is_path_dir(char * filename);

/* Commands */  
static ngx_command_t  ngx_http_move_domain_cache_commands[] = {  
    { ngx_string("mv_cache"),  
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,  
      ngx_http_move_domain_cache,  
      0,  
      0,  
      NULL },  
    ngx_null_command  
};  
  
//static u_char ngx_move_domain_cache[] = "hello world";  

static u_char ngx_domain_cache_path[] = "/home/cache/"; 

static ngx_http_module_t  ngx_http_move_domain_cache_module_ctx = {  
    NULL,                                  /* preconfiguration */  
    NULL,                                     /* postconfiguration */  
    NULL,                                  /* create main configuration */  
    NULL,                                  /* init main configuration */  
    NULL,                                  /* create server configuration */  
    NULL,                                  /* merge server configuration */  
    NULL,                                  /* create location configuration */  
    NULL                                   /* merge location configuration */  
};  
/* hook */  
ngx_module_t  ngx_http_move_domain_cache_module = {  
    NGX_MODULE_V1,  
    &ngx_http_move_domain_cache_module_ctx,              /* module context */  
    ngx_http_move_domain_cache_commands,                 /* module directives */  
    NGX_HTTP_MODULE,                       /* module type */  
    NULL,                                  /* init master */  
    NULL,                                  /* init module */  
    NULL,             /* init process */  
    NULL,                                  /* init thread */  
    NULL,                                  /* exit thread */  
    NULL,             /* exit process */  
    NULL,                                  /* exit master */  
    NGX_MODULE_V1_PADDING  
};

static ngx_int_t  
ngx_http_move_domain_cache_handler(ngx_http_request_t *r)  
{  

    ngx_buf_t    *b;  
    ngx_chain_t   out;  
    ngx_str_t domain;
    u_char *cache_path;
    ngx_int_t path_len ; 

    domain.data = r->headers_in.server.data;
    domain.len = ngx_strlen(domain.data);

    cache_path = ngx_pcalloc(r->pool,domain.len + sizeof(ngx_domain_cache_path));
    path_len = ngx_strlen(ngx_domain_cache_path);
    ngx_memcpy(cache_path,ngx_domain_cache_path,path_len);
    ngx_memcpy(&cache_path[path_len],domain.data,domain.len);
    
    /* Http Output Buffer */
    if (ngx_delete_cache_dir((char *)cache_path,r) == NGX_FILE_ERROR) {
        /* entry in error log is enough, don't notice client */
        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                      ngx_delete_file_n " \"%s\" failed", cache_path);
    }

    r->headers_out.content_type.len = sizeof("text/html") - 1;  
    r->headers_out.content_type.data = (u_char *) "text/html"; 
    //why not malloc memory from stack
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));  
      
    out.buf = b;  
    out.next = NULL;  

    b->pos = cache_path;  
    b->last = domain.data + domain.len + sizeof(ngx_domain_cache_path);  

    b->memory = 1;  
    b->last_buf = 1;  
      
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = domain.len + sizeof(ngx_domain_cache_path);

    ngx_http_send_header(r);  
      
    return ngx_http_output_filter(r, &out);  
}

static char *  
ngx_http_move_domain_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
{  
    ngx_http_core_loc_conf_t *clcf ;  
    /* register hanlder */  
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);  
    clcf->handler = ngx_http_move_domain_cache_handler;  
    return NGX_CONF_OK;  
}  

static ngx_int_t
ngx_is_path_dir(char * filename)
{
        struct stat buf;
        ngx_int_t ret = stat(filename,&buf);
        if(0 == ret)
        {
            if(buf.st_mode & S_IFDIR)
            {
                    return 0;
            }
            else
            {
                    return 1;
            }
        }
        return -1;
}

static ngx_int_t
ngx_delete_cache_dir(char * dirname,ngx_http_request_t *r)
{
        char *chBuf;
        DIR * dir = NULL;
        struct dirent *ptr;
        ngx_int_t ret = 0;

        dir = opendir(dirname);
        if(NULL == dir)
        {
            return -1;
        }

        chBuf = ngx_pcalloc(r->pool,256);
        while((ptr = readdir(dir)) != NULL)
        {
                ret = strcmp(ptr->d_name, ".");
                if(0 == ret)
                {
                        continue;
                }

                ret = strcmp(ptr->d_name, "..");
                if(0 == ret)
                {
                    continue;
                }

                snprintf(chBuf, 256, "%s/%s", dirname, ptr->d_name);
                ret = ngx_is_path_dir(chBuf);
                if(0 == ret)
                {
                    ret = ngx_delete_cache_dir(chBuf,r);
                    if(0 != ret)
                    {
                            return -1;
                    }
                }
                else if(1 == ret)
                {
                    ret = remove(chBuf);
                    if(0 != ret)
                    {
                        return -1;
                    }
                }
        }
    (void)closedir(dir);

    ret = remove(dirname);
    if(0 != ret)
    {
        return -1;
    }
    return 0;
}

使用

访问 http://domain/mv_cache 就行,比如 http://www.firefoxbug.com/mv_cache 就能清除 /home/cache/ 下的域名。

标签:C/C++, Linux, Nginx

评论已关闭