nginx共享内存小窥

创建

先在ngx_init_cycle()里分配一个元素(ngx_shm_zone_t)

ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)

以ngx_http_limit_conn_module限速模块为例来进行讲解
当解析到指令limit_conn_zone的时候,调用相应的回调函数ngx_http_limit_conn_zone()
该回调通过ngx_shared_memory_add()中的ngx_list_push()使用一个shm元素(ngx_shm_zone_t)
该元素的shm.size、shm.name、tag分别是shm大小、shm名字、模块地址(&ngx_http_limit_conn_module)
该元素的init是回调函数ngx_http_limit_conn_init_zone(),它将在配置解析完后被ngx_init_cycle()调用用于创建红黑树来存放记录

ngx_shared_memory_add(cf, &name, size, &ngx_http_limit_conn_module);
  ngx_list_push(&cf->cycle->shared_memory);

挂载

当解析到指令limit_conn的时候,调用相应的回调函数ngx_http_limit_conn()
通过ngx_shared_memory_add()获得之前建立好的shm,该函数的逻辑是通过参数2和4的比较获得相应shm元素
ngx_shared_memory_add(cf, &value[1], 0, &ngx_http_limit_conn_module);
该模块的配置项结构体ngx_http_limit_conn_conf_t中有一个成员表示限速记录块数组(ngx_array_t),数组每个成员都有2个子成员:ngx_shm_zone_t* 和 ngx_unit_t,分别表示shm的指针以及限速阈值
以上就是解析配置的过程,解析结束后,该模块把自己的处理函数ngx_http_limit_conn_handler()放到请求处理的preaccess阶段,它用于在请求处理的时候维护该sm中的记录

初始化

解析完配置后,要真正为shm申请和初始化虚拟空间:
首先,通过mmap()申请虚拟内存,此时并没有真正分配物理内存
然后,ngx_init_zone_pool()首先会在该shm区域开头放置它的内存管理结构ngx_slab_pool_t,然后创建锁,然后初始化内存管理结构
最后,调用该shm区域所属的模块所注册的回调函数,此处是ngx_http_limit_conn_init_zone(),它在shm区域里创建一个空红黑树,即此shm的记录集以红黑树的形式存在

ngx_shm_alloc(&shm_zone[i].shm)
    shm->addr = (u_char *) mmap(NULL, shm->size,PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
ngx_init_zone_pool(cycle, &shm_zone[i]);   
    sp = (ngx_slab_pool_t *) zn->shm.addr;
    ngx_shmtx_create(&sp->mutex, &sp->lock, file);
    ngx_slab_init(sp);
shm_zone[i].init(&shm_zone[i], NULL)

使用

处理函数ngx_http_limit_conn_handler()在每次请求到来时都要对并发连接数进行检查:
首先,将key进行哈希
然后,对该shm区域加锁,无限循环中执行加锁、cpu_pause中执行加锁、等待信号量,成功则返回。加锁操作就是把mtx->lock设置成自己的进程pid
然后,执行红黑树查询。先比较哈希值,再比较字符串
然后,解锁。先把mtx->locl设置成0,释放信号量
最后,如果并发数达到阈值,则拒绝请求,并执行cleanup将连接数减1;否则将回调函数ngx_http_limit_conn_cleanup()挂载到请求结构体的内存池中,这样在请求结束后,内存池销毁的时候会自动执行所有的cleaup函数,其中该回调函数会将连接数减1,

hash = ngx_crc32_short(key.data, key.len);
ngx_shmtx_lock(&ctx->shpool->mutex);
node = ngx_http_limit_conn_lookup(&ctx->sh->rbtree, &key, hash);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值