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;
}

最新文章

  1. Android之文件数据存储
  2. ActiveMQ学习笔记(5)——使用Spring JMS收发消息
  3. Hibernate连接mysql数据库并自动创建表
  4. AC日记——字符串的展开 openjudge 1.7 35
  5. Fragemnt和TextView的交互(TextView在LinearLayout中)
  6. C语言笔试常考知识点
  7. 浏览器对象模型(BOM,Browser Object Model)
  8. Gradle教程之任务管理
  9. linux innode图解2
  10. 前端学习笔记(zepto或jquery)—— 布局技巧(一)
  11. 【repost】js字符串函数
  12. sed从入门到深入修炼目录
  13. ToolStrip和MenuStrip控件簡介及常用屬性(转)
  14. UVA1374 IDA*
  15. go生成不重复的纯数字6位的随机数
  16. iptables的MAC地址过滤
  17. 第三篇-以LinearLayout进行Android界面设计
  18. ACM__并查集
  19. paxos协议
  20. Mac下Python与Kafka的配合使用

热门文章

  1. leetcode-62. Unique Paths &#183; DP + vector
  2. python中yield的用法详解-转载
  3. Python爬虫之用脚本登录Github并查看信息
  4. 15_sqoop数据导出
  5. [Python] For 嵌套循环打印图形 nested loop-练习题答案
  6. idou老师教你学Istio 22 : 如何用istio实现调用链跟踪
  7. jquery中的ajaxSetup
  8. ThreadLocal 是什么?(未完成)有哪些使用场景?(未完成)
  9. Web UI开发速速种草—Kendo UI for jQuery网格编辑操作概述
  10. 2019牛客暑期多校训练营(第五场)F maximum clique 1 二分图求最大独立集