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;
}
OpenResty之 lua_shared_dict 指令的更多相关文章
- 《用OpenResty搭建高性能服务端》笔记
概要 <用OpenResty搭建高性能服务端>是OpenResty系列课程中的入门课程,主讲人:温铭老师.课程分为10个章节,侧重于OpenResty的基本概念和主要特点的介绍,包括它的指 ...
- OpenResty学习指南(一)
我的博客: https://www.luozhiyun.com/archives/217 想要学好 OpenResty,你必须理解下面 8 个重点: 同步非阻塞的编程模式: 不同阶段的作用: LuaJ ...
- OpenResty和Resis一些基本的性能配置
Basics: 1. Ensure that you have not disabled Lua code cache: https://github.com/openresty/lua-nginx- ...
- openresty域名动态解析
工作中使用openresty,使用第三方服务API通过域名访问.但是,域名通过DNS解析出来之后,在openresty是有 配置解析阶段 很多时候我们会在 Nginx 配置文件里配置上一些域名,比如配 ...
- 【技术干货】听阿里云CDN安防技术专家金九讲tengine+lua开发
一.介绍 二.安装 三.运行 四.开发 1.介绍 Tengine:轻量级.高性能.高并发.配置化.模块化.可扩展.可移植的Web和反向代理 服务器,Tengine是nginx超集,但做了很多优化,包含 ...
- Redis与DB的数据一致性解决方案(史上最全)
文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...
- 高并发 Nginx+Lua OpenResty系列(3)——模块指令
Nginx Lua 模块指令 Nginx共11个处理阶段,而相应的处理阶段是可以做插入式处理,即可插拔式架构:另外指令可以在http.server.server if.location.locatio ...
- OpenResty之指令与常用API
1. 指令 通过 Lua 编写 Nginx 脚本的基本构建块是指令.指令常用于指定 Lua 代码是几时执行的以及如何使用运行的结果.下图展示了指令执行的顺序. lua_capture_error_lo ...
- 用Nginx+Lua(OpenResty)开发高性能Web应用
在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Nginx开 ...
随机推荐
- eclipse导入项目后出现红色叉号的解决方案
对于一名程序员来说,我导入的项目在项目的名称上无端加了一个红色的叉号,虽然这个不友好的符号,对于我整个的项目运行没有任何影响,但是总让我觉得不舒服,大大的叉号写在我的项目的脑袋上,我心里能舒服吗?于是 ...
- zabbix-通过自动发现添加主机
当生产环境中需要监控海量的机器的时候,特别是像58.赶集这类同城性质的大网站,或者京东.阿里云这样的造节电商,每次活动.大促都需要添加很多机器来应对海量用户流量,每天都有可能上架新的机器.或者添加新的 ...
- 《浏览器工作原理与实践》<11>this:从JavaScript执行上下文的视角讲清楚this
在上篇文章中,我们讲了词法作用域.作用域链以及闭包,接下来我们分析一下这段代码: var bar = { myName:"time.geekbang.com", printName ...
- SQL Server 对接MySQL 数据库
1.在SQL SERVER服务器上安装MYSQL ODBC驱动; 驱动下载地址:http://dev.mysql.com/downloads/connector/odbc/ 2.安装好后,在管理工具- ...
- SQL ISNULL 参数
SQL Server 中有两个参数,语法: ISNULL(check_expression, replacement_value) check_expression 与 replacement ...
- ICPC2019上海站游记
银牌第4,差4名拿金 金牌就保研国奖,银牌就什么都没有 最痛苦的是功败垂成 也许签到罚时太多罢,也许构造做得太晚罢,也许J题没有做出来罢 翻来覆去,似乎也想不到得金的理由 福兮祸所倚 年轻人多遇到点挫 ...
- java学习笔记14-多态
多态可以理解为同一个操作在不同对象上会有不同的表现 比如在谷歌浏览器上按F1会弹出谷歌的帮助页面.在windows桌面按F1会弹出windows的帮助页面. 多态存在的三个必要条件: 继承 重写 父类 ...
- appium+python 【Mac】UI自动化测试封装框架介绍 <五>---脚本编写(多设备)
目的: 通过添加设备号,则自动给添加的设备分配端口,启动对应的appium服务.注意:为了方便,将共用一个配置文件. 1.公共的配置文件名称:desired_caps.yaml platformVer ...
- Java锁--共享锁和ReentrantReadWriteLock
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3505809.html ReadWriteLock 和 ReentrantReadWriteLock介绍 ...
- Java集合--ArrayList,LinkedList性能分析
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3308900.html 第1部分 List概括 先回顾一下List的框架图 (01) List 是一个接口 ...