zoukankan      html  css  js  c++  java
  • OpenResty之 lua_shared_dict 指令

    1. lua_shared_dict 指令介绍

    原文: lua_shared_dict

    syntax:lua_shared_dict <name> <size>
    default: no
    context: http
    phase: depends on usage
    

    声明一个共享内存区域 name,以充当基于 Lua 字典 ngx.shared.<name> 的共享存储。

    共享内存总是被当前 Nginx 服务器实例中所有的 Nginx worker 进程所共享。

    size 参数接受大小单位,如 k,m:

    http {
        lua_shared_dict dogs 10m;
        ...
    }
    

    详细参见: ngx.shared.DICT

    2. 源码分析

    lua_shared_dict 指令位于 ngx_http_lua_module.c 文件中:

    static ngx_command_t ngx_http_lua_cmds[] = {
        ...
        
        { ngx_string("lua_shared_dict"),
          NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,
          ngx_http_lua_shared_dict,
          0,
          0, 
          NULL },
        
        ...
    }
    

    2.1 ngx_http_lua_shared_dict

    char *
    ngx_http_lua_shared_dict(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        ngx_http_lua_main_conf_t   *lmcf = conf;
        
        ngx_str_t                  *value, name;
        ngx_shm_zone_t             *zone;
        ngx_shm_zone_t            **zp;
        ngx_http_lua_shdict_ctx_t  *ctx;
        ssize_t                     size;
        
        if (lmcf->shdict_zones == NULL) {
            lmcf->shdict_zones = ngx_palloc(cf->pool, sizeof(ngx_array_t));
            if (lmcf->shdict_zones == NULL) {
                return NGX_CONF_ERROR;
            }
            
            if (ngx_array_init(lmcf->shdict_zones, cf->pool, 2, 
                               sizeof(ngx_shm_zone_t *))
                != NGX_OK)
            {
                return NGX_CONF_ERROR;
            }
        }
        
        value = cf->args->elts;
        
        ctx = NULL;
        
        if (value[1].len == 0) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "invalid lua shared dict name "%V""", &value[1]);
            return NGX_CONF_ERROR;
        }
        
        /* 共享内存的名称 */
        name = value[1];
        
        /* 解析需要分配的共享内存大小 */
        size = ngx_parse_size(&value[2]);
        
        if (size <= 8191) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 
                               "invalid lua shared dict size "%V"", &value[2]);
            return NGX_CONF_ERROR;
        }
        
        ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_shdict_ctx_t));
        if (ctx == NULL) {
            return NGX_CONF_ERROR;
        }
        
        ctx->name = name;
        ctx->main_conf = lmcf;
        ctx->log = &cf->cycle->new_log;
        
        zone = ngx_http_lua_shared_memory_add(cf, &name, (size_t) size, 
                                              &ngx_http_lua_module);
        if (zone == NULL) {
            return NGX_CONF_ERROR;
        }
        
        if (zone->data) {
            ctx = zone->data;
            
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 
                               "lua_shared_dict "\%V" is already defined as "
                               "\%V"", &name, &ctx->name);
            return NGX_CONF_ERROR;
        }
        
        zone->init = ngx_http_lua_shdict_init_zone;
        zone->data = ctx;
        
        zp = ngx_array_push(lmcf->shdict_zones);
        if (zp == NULL) {
            return NGX_CONF_ERROR;
        }
        
        *zp = zone;
        
        lmcf->requires_shm = 1;
        
        return NGX_CONF_OK;
    }
    

    2.2 ngx_http_lua_shared_memory_add

    ngx_shm_zone_t *
    ngx_http_lua_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, 
        void *tag)
    {
        ngx_http_lua_main_conf_t     *lmcf;
        ngx_shm_zone_t              **zp;
        ngx_shm_zone_t               *zone;
        ngx_http_lua_shm_zone_ctx_t  *ctx;
        ngx_int_t                     n;
        
        lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_module);
        if (lmcf == NULL) {
            return NULL;
        }
        
        if (lmcf->shm_zones == NULL) {
            lmcf->shm_zones = ngx_palloc(cf->pool, sizeof(ngx_array_t));
            if (lmcf->shm_zones == NULL) {
                return NULL;
            }
            
            if (ngx_array_init(lmcf->shm_zones, cf->pool, 2, 
                               sizeof(ngx_shm_zone_t *))
                != NGX_OK)
            {
                return NULL;
            }
        }
        
        /* 分配一个代表共享内存的结构体 ngx_shm_zone_t,并将其插入到 
         * cf->cycle->shared_memory 链表中 */
        zone = ngx_shared_memory_add(cf, name, (size_t) size, tag);
        if (zone == NULL) {
            return NULL;
        }
        
        if (zone->data) {
            ctx = (ngx_http_lua_shm_zone_ctx_t *) zone->data;
            return &ctx->zone;
        }
        
        n = sizeof(ngx_http_lua_shm_zone_ctx_t);
        
        ctx = ngx_pcalloc(cf->pool, n);
        if (ctx == NULL) {
            return NULL;
        }
        
        ctx->lmcf = lmcf;
        ctx->log = &cf->cycle->new_log;
        ctx->cycle = cf->cycle;
        
        ngx_memcpy(&ctx->zone, zone, sizeof(ngx_shm_zone_t));
        
        zp = ngx_array_push(lmcf->shm_zones);
        if (zp == NULL) {
            return NULL;
        }
        
        *zp = zone;
        
        /* 设置在 init_cycle 中真正创建共享内存时调用的初始化函数,
         * 该 init 函数是各个共享内存所特定的,根据使用方的自身需求不同
         * 而不同 */
        /* set zone init */
        zone->init = ngx_http_lua_shared_memory_init;
        zone->data = ctx;
        
        lmcf->requires_shm = 1;
        
        return &ctx->zone;
    }
    

    在 init_cycle 函数中:

    {
        ...
        
        /* create shared memory */
    
        part = &cycle->shared_memory.part;
        shm_zone = part->elts;
     
        for (i = 0; /* void */ ; i++) {
            ...
            
            if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) {
                goto failed;
            }
    
            if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
                goto failed;
            }
    
            /* 指向每个模块所创建的共享内存所特有的 init 函数 */
            if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
                goto failed;
            }
        }
     
        ...   
    }
    

    对于 ngx_http_lua_module 模块的 lua_shared_dict 指令所创建的共享内存的 init 函数为 ngx_http_lua_shared_memory_init。

    2.3 ngx_http_lua_shared_memory_init

    static ngx_int_t 
    ngx_http_lua_shared_memory_init(ngx_shm_zone_t *shm_zone, void *data)
    {
        ngx_http_lua_shm_zone_ctx_t *octx = data;
        ngx_shm_zone_t              *ozone;
        void                        *odata;
        
        ngx_int_t                    rc;
        volatile ngx_cycle_t        *saved_cycle;
        ngx_http_lua_main_conf_t    *lmcf;
        ngx_http_lua_shm_zone_ctx_t *ctx;
        ngx_shm_zone_t              *zone;
        
        ctx = (ngx_http_lua_shm_zone_ctx_t *) shm_zone->data;
        zone = &ctx->zone;
        
        odata = NULL;
        if (octx) {
            ozone = &octx->zone;
            odata = ozone->data;
        }
        
        zone->shm = shm_zone->shm;
    #if defined(nginx_version) && nginx_version >= 1009000
        zone->noreuse = shm_zone->noreuse;
    #endif
        
        /* 指向 ngx_http_lua_shdict_init_zone 函数 */
        if (zone->init(zone, odata) != NGX_OK) {
            return NGX_ERROR;
        }
        
        dd("get lmcf");
        
        lmcf = ctx->lmcf;
        if (lmcf == NULL) {
            return NGX_ERROR;
        }
        
        dd("lmcf->lua: %p", lmcf->lua);
        
        lmcf->shm_zones_inited++;
        
        if (lmcf->shm_zones_inited == lmcf->shm_zones->nelts 
            && lmcf->init_handler) 
        {
            saved_cycle = ngx_cycle;
            ngx_cycle = ctx->cycle;
            
            rc = lmcf->init_handler(ctx->log, lmcf, lmcf->lua);
            
            ngx_cycle = saved_cycle;
            
            if (rc != NGX_OK) {
                /* an error happened */
                return NGX_ERROR;
            }
        }
        
        return NGX_OK;
        
    }
    

    2.4 ngx_http_lua_shdict_init_zone

    ngx_int_t 
    ngx_http_lua_shdict_init_zone(ngx_shm_zone_t *shm_zone, void *data)
    {
        ngx_http_lua_shdict_ctx_t  *octx = data;
        
        size_t                      len;
        ngx_http_lua_shdict_ctx_t  *ctx;
        
        dd("init zone");
        
        ctx = shm_zone->data;
        
        if (octx) {
            ctx->sh = octx->sh;
            ctx->shpool = octx->shpool;
            
            return NGX_OK;
        }
        
        ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
        
        if (shm_zone->shm.exists) {
            ctx->sh = ctx->shpool->data;
            
            return NGX_OK;
        }
        
        ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_lua_shdict_shctx_t));
        if (ctx->sh == NULL) {
            return NGX_ERROR;
        }
        
        ctx->shpool->data = ctx->sh;
        
        ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, 
                        ngx_http_lua_shdict_rbtree_insert_value);
        
        ngx_queue_init(&ctx->sh->lru_queue);
        
        len = sizeof(" in lua_shared_dict zone """) + shm_zone->shm.name.len;
        
        ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
        if (ctx->shpool->log_ctx == NULL) {
            return NGX_ERROR;
        }
        
        ngx_sprintf(ctx->shpool->log_ctx, " in lua_shared_dict zone "%V"%Z",
                    &shm_zone->shm.name);
        
    #if defined(nginx_version) && nginx_version >= 1005013
        ctx->shpool->log_nomem = 0;
    #endif
    
        return NGX_OK;
    }
    
  • 相关阅读:
    JS组件系列——表格组件神器:bootstrap table
    wcf寄宿到iis
    win10获取注册表权限
    在唯一密钥属性“fileExtension”设置为“.log”时,无法添加类型为“mimeMap”的重复集合项
    从TFS中的现有项目复制一份作为新项目,导致提交的服务器无法加载
    对程序集“”签名时加密失败 --“对程序集签名时出错
    session
    升级webapi依赖的Newtonsoft.json的版本(转)
    多线程相关
    Linq Group By 多个字段
  • 原文地址:https://www.cnblogs.com/jimodetiantang/p/9410622.html
Copyright © 2011-2022 走看看