• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

OpenResty之 lua_shared_dict 指令

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

原文: 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;
}

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Lua 脚本 控制 XML配置 - 之Lua学习1 ( 多维嵌套表的 C API 交互)发布时间:2022-07-22
下一篇:
Lua入门级笔记摘要发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap