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

OpenResty之 lua_shared_dict 指令的更多相关文章

  1. 《用OpenResty搭建高性能服务端》笔记

    概要 <用OpenResty搭建高性能服务端>是OpenResty系列课程中的入门课程,主讲人:温铭老师.课程分为10个章节,侧重于OpenResty的基本概念和主要特点的介绍,包括它的指 ...

  2. OpenResty学习指南(一)

    我的博客: https://www.luozhiyun.com/archives/217 想要学好 OpenResty,你必须理解下面 8 个重点: 同步非阻塞的编程模式: 不同阶段的作用: LuaJ ...

  3. OpenResty和Resis一些基本的性能配置

    Basics: 1. Ensure that you have not disabled Lua code cache: https://github.com/openresty/lua-nginx- ...

  4. openresty域名动态解析

    工作中使用openresty,使用第三方服务API通过域名访问.但是,域名通过DNS解析出来之后,在openresty是有 配置解析阶段 很多时候我们会在 Nginx 配置文件里配置上一些域名,比如配 ...

  5. 【技术干货】听阿里云CDN安防技术专家金九讲tengine+lua开发

    一.介绍 二.安装 三.运行 四.开发 1.介绍 Tengine:轻量级.高性能.高并发.配置化.模块化.可扩展.可移植的Web和反向代理 服务器,Tengine是nginx超集,但做了很多优化,包含 ...

  6. Redis与DB的数据一致性解决方案(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  7. 高并发 Nginx+Lua OpenResty系列(3)——模块指令

    Nginx Lua 模块指令 Nginx共11个处理阶段,而相应的处理阶段是可以做插入式处理,即可插拔式架构:另外指令可以在http.server.server if.location.locatio ...

  8. OpenResty之指令与常用API

    1. 指令 通过 Lua 编写 Nginx 脚本的基本构建块是指令.指令常用于指定 Lua 代码是几时执行的以及如何使用运行的结果.下图展示了指令执行的顺序. lua_capture_error_lo ...

  9. 用Nginx+Lua(OpenResty)开发高性能Web应用

    在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Nginx开 ...

随机推荐

  1. 使用 keytool 生成安卓应用程序签名

    下载 keytool jar包: 解压jar包到固定目录 如: cd  /Library/Java/JavaVirtualMachines/ 进入到jar包目录: cd /Library/Java/J ...

  2. JavaScript--常用对象的属性及方法(3)

    String对象(字符串) 字符串在本质上也是数组 都可以通过str[i]访问内容 但是数组创建后可以修改 而字符串一旦创建内容不可更改 属性:length 作用与数组相同 获取字符串的长度 方法: ...

  3. BPM软件_财务报销流程管理解决方案_K2工作流引擎

    财务报销,对任何企业都是日常运营中重要的一个环节.但报销流程周期长,反复签字手续繁杂,报销过程不透明 ,单据归档保存.检索困难等问题也让员工头疼.为了解决这些困扰,财务报销流程电子化一时成为热门之选. ...

  4. zabbix-将业务机器加入到监控中

    一.设置被监控的机器 1. 配置主机名 echo "agent.test.com" > /etc/hostname hostname agent.test.com 2.安装z ...

  5. linux——运维基础,与常用命令

    1 运维概述 1 什么是运维 服务器的运行维护 2 名词 IDC(互联网数据中心) 3 监控软件 zabbix(用的最多), nagios, cactti 4 常用的linux操作系统 1 CentO ...

  6. Image Processing and Analysis_8_Edge Detection:Design of steerable filters for feature detection using canny-like criteria ——2004

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  7. 跟着minium官网介绍学习minium-----(一)

    某天,再打开微信开发者工具的时候收到一条推送.说是微信小程序自动化框架 Python 版 -- Minium 公测. Url如下: https://developers.weixin.qq.com/c ...

  8. httpd源码编译安装

    什么是编译安装——编译:将源代码变为机器可执行的代码文件.安装:将可执行文件安装到操作系统里,才可以使用. 一.下载httpd源码包 在官网上下载httpd源码包http://httpd.apache ...

  9. web.py之cookie和session

    官方给的session例子这里就不讲了.下面直接将怎么设置session,取session: session相关代码一定要放在web.py框架的Main.py里面. # Main.py # 设置ses ...

  10. maven jar 包不在项目中

    maven  update project maven build