原文: lua_shared_dictnginx
syntax:lua_shared_dict <name> <size> default: no context: http phase: depends on usage
聲明一個共享內存區域 name,以充當基於 Lua 字典 ngx.shared.<name>
的共享存儲。git
共享內存老是被當前 Nginx 服務器實例中全部的 Nginx worker 進程所共享。github
size 參數接受大小單位,如 k,m:服務器
http { lua_shared_dict dogs 10m; ... }
詳細參見: ngx.shared.DICTapp
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 }, ... }
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; }
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。ui
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; }
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; }