Nginx 缓存机制 详解之二 缓存加载进程

来源:互联网 发布:c语言二级考试选择题 编辑:程序博客网 时间:2024/05/17 02:48

上一篇博客已经详细讲解了缓存管理进程,接下来详细讲解缓存加载进程机制

缓存加载进程机制

ngx_cache_loader_process_handler函数

加载进程 和管理进程都是从函数ngx_cache_manager_process_cycle进入,只是接下来的流程函数不一样

ngx_process_events_and_timers()->ngx_event_expire_timers()->ngx_cache_loader_process_handler()
static ngx_cache_manager_ctx_t  ngx_cache_loader_ctx = {    ngx_cache_loader_process_handler, "cache loader process", 60000};static voidngx_cache_loader_process_handler(ngx_event_t *ev){    ngx_uint_t     i;    ngx_path_t   **path;    ngx_cycle_t   *cycle;    cycle = (ngx_cycle_t *) ngx_cycle;    path = cycle->paths.elts;    for (i = 0; i < cycle->paths.nelts; i++) {        if (ngx_terminate || ngx_quit) {            break;        }        if (path[i]->loader) {            path[i]->loader(path[i]->data); //这里的 loader调用的 是ngx_http_file_cache_loader()            ngx_time_update();        }    }    exit(0);

ngx_http_file_cache_loader函数

static voidngx_http_file_cache_loader(void *data){    ngx_http_file_cache_t  *cache = data;    ngx_tree_ctx_t  tree;    if (!cache->sh->cold || cache->sh->loading) {        return;    }    if (!ngx_atomic_cmp_set(&cache->sh->loading, 0, ngx_pid)) {        return;    }    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,                   "http file cache loader");   //设置回调    tree.init_handler = NULL;    tree.file_handler = ngx_http_file_cache_manage_file; // 对于每个cache文件调用这个回调    tree.pre_tree_handler = ngx_http_file_cache_manage_directory;//主要用来遍历所有cache的 目录     tree.post_tree_handler = ngx_http_file_cache_noop;    tree.spec_handler = ngx_http_file_cache_delete_file;    //回调数据就是cache    tree.data = cache;    tree.alloc = 0;    tree.log = ngx_cycle->log;   //last为最后load时间    cache->last = ngx_current_msec;    cache->files = 0;   //开始遍历    if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) {        cache->sh->loading = 0;        return;    }

上面有一个ngx_tree_ctx_t数据结构

struct ngx_tree_ctx_s {    off_t                      size;    off_t                      fs_size;    ngx_uint_t                 access;    time_t                     mtime;    ngx_tree_init_handler_pt   init_handler;    ngx_tree_handler_pt        file_handler;    ngx_tree_handler_pt        pre_tree_handler;    ngx_tree_handler_pt        post_tree_handler;    ngx_tree_handler_pt        spec_handler;    void                      *data;    size_t                     alloc;    ngx_log_t                 *log;};/**ctx->init_handler() – see ctx->alloc* ctx->file_handler() – file handler* ctx->pre_tree_handler() – handler is called before entering directory* ctx->post_tree_handler() – handler is called after leaving directory* ctx->spec_handler() – special (socket, FIFO, etc.) file handler** ctx->data – some data structure, it may be the same on all levels, or* reallocated if ctx->alloc is nonzero** ctx->alloc – a size of data structure that is allocated at every level* and is initilialized by ctx->init_handler()** ctx->log – a log*/

ngx_http_file_cache_manage_file函数

static ngx_int_tngx_http_file_cache_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path){    ngx_msec_t              elapsed;    ngx_http_file_cache_t  *cache;    cache = ctx->data;//将文件添加进cache    if (ngx_http_file_cache_add_file(ctx, path) != NGX_OK) {        (void) ngx_http_file_cache_delete_file(ctx, path);    }//如果文件个数太大,则休眠并清理files计数    if (++cache->files >= cache->loader_files) {        ngx_http_file_cache_loader_sleep(cache);    } else {        ngx_time_update();//否则看loader时间是不是过长,如果过长则又进入休眠        elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last));        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,                       "http file cache loader time elapsed: %M", elapsed);        if (elapsed >= cache->loader_threshold) {            ngx_http_file_cache_loader_sleep(cache);        }    }    return (ngx_quit || ngx_terminate) ? NGX_ABORT : NGX_OK;}

分别是ngx_http_file_cache_add_file和ngx_http_file_cache_loader_sleep。其中sleep函数比较简单,就是休眠,并重置对应的域。

ngx_http_file_cache_loader_sleep函数

static voidngx_http_file_cache_loader_sleep(ngx_http_file_cache_t *cache){    ngx_msleep(cache->loader_sleep);    ngx_time_update();    cache->last = ngx_current_msec;    cache->files = 0;}

ngx_http_file_cache_add_file函数

ngx_http_file_cache_add_file,它主要是通过文件名计算hash,然后调用ngx_http_file_cache_add将这个文件加入到cache管理中(也就是添加红黑树以及队列)

static ngx_int_tngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c){    ngx_http_file_cache_node_t  *fcn;    ngx_shmtx_lock(&cache->shpool->mutex);//首先查找    fcn = ngx_http_file_cache_lookup(cache, c->key);    if (fcn == NULL) {//如果不存在,则新建结构        fcn = ngx_slab_alloc_locked(cache->shpool,                                    sizeof(ngx_http_file_cache_node_t));        if (fcn == NULL) {            ngx_shmtx_unlock(&cache->shpool->mutex);            return NGX_ERROR;        }        ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t));        ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],                   NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));//插入红黑树        ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);        fcn->uses = 1;        fcn->count = 0;        fcn->valid_msec = 0;        fcn->error = 0;        fcn->exists = 1;        fcn->updating = 0;        fcn->deleting = 0;        fcn->uniq = 0;        fcn->valid_sec = 0;        fcn->body_start = 0;        fcn->fs_size = c->fs_size;        cache->sh->size += c->fs_size;    } else {//否则删除queue,后续会重新插入        ngx_queue_remove(&fcn->queue);    }    fcn->expire = ngx_time() + cache->inactive;//重新插入    ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);    ngx_shmtx_unlock(&cache->shpool->mutex);    return NGX_OK;}
0 0
原创粉丝点击