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开 ...
随机推荐
- BeginInvoke异步线程
this.BeginInvoke(new Action(() => { dataGridView1.DataSource = BLLBillConsume.BllGetClearMarketLo ...
- dfs · leetcode-22.产生括号组?
题面 Given n pairs of parentheses, write a function to generate all combinations of well-formed parent ...
- ES date_histogram 聚合
如下 GET cars/index/_search { "size":0, "aggs": { "sales": { "date_ ...
- Ubuntu 手动挂载exfat格式的U盘
1.默认Ubuntu不支持exFat格式的U盘,先要安装支持: sudo apt-get install exfat-fuse 2.挂载磁盘,我选择挂在mnt下面 a.创建挂载目录:sudo mkdi ...
- zabbix low-level discovery 监控mysql
当一台服务器上MySQL有多个实例的时候,MySQL占用多个不同端口.利用zabbix的low-level discovery可以轻松监控. 思路参考:http://dl528888.blog.51c ...
- 浏览器获取当前ip
function findIP(callback) { var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConn ...
- python3 准备
一.前言 1.Python是著名的“龟叔”Guido van Rossum发明的 2.python分为python2和python3两大版本,python2渐渐被淘汰,建议使用python3 3.py ...
- 通过字节码分析Java方法的静态分派与动态分派机制
在上一次[https://www.cnblogs.com/webor2006/p/9723289.html]中已经对Java方法的静态分派在字节码中的表现了,也就是方法重载其实是一种静态分派的体现,这 ...
- B-Tree目录和Hash索引的区别
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...
- .npmrc 实用小技巧
小技巧 因为每次执行 npm adduser 的时候都需要输入用户名.密码和email 很麻烦,我们都可以配置在.npmrc 文件中,在命令行中执行如下脚本 echo -n 'myuser:mypas ...