您的位置:首页 > 运维架构 > Nginx

Nginx基础. Nginx模块上下文

2015-09-08 22:54 597 查看
这里要提到的上下文是针对HTTP请求的, 每个HTTP请求对应于每一个HTTP模块都可以有一个独立的上下文结构体.(可以看出, 并不是一个HTTP请求的上下文由所有HTTP模块共享)

每个请求对于每个模块的上下文结构体一般是在刚开始处理请求时在内存池分配它. 之后经过epoll, HTTP框架再次调用到HTTP模块的处理方法时, 这个HTTP模块可以由请求的上下文结构中获取信息. 在请求结束后, 其对应的内存池被释放, 申请的上下文也就被释放了. 因为上下文是针对某请求的某一个模块的, 所以如果某模块不需要上下文, 完全可以不理会.

为什么使用?

之所以使用上下文, 是因为Nginx是一个全异步处理的Web服务器, 1个请求并不会在epoll的一次调度中处理完成, 甚至会在成千上万的HTTP模块后才能完成请求的处理.

哪些接口?

既然上下文是针对某请求的某模块的, 那么可以根据前文中, 存储某模块存储create_main_conf函数返回的结构体的方式了解到, 其实所有模块在每个请求中都对应了数组的一个元素, 所以可以根据数组下标来找到对应模块的数据.

使用上下文的方式就是调用下面这两个宏:

#define ngx_http_get_module_ctx(r, module)  (r)->ctx[module.ctx_index]
#define ngx_http_set_ctx(r, c, module)      r->ctx[module.ctx_index] = c;


如何使用?

下面提供一个例子:

//首先建立上下文的结构体
typedef struct{
ngx_uint_t ben_count;
}ngx_ben_test_ctx_t;

//当请求第一次进入ben_test模块处理时, 我们需要创建一个ngx_ben_test_ctx_t结构体, 并设置到请求中去
static ngx_int_t
ngx_http_ben_test(ngx_http_request_t *r)
{
//首先调用ngx_http_get_module_ctx获取此模块的上下文结构体(可以预料, 既然这是第一次进入此模块处理, 这个上下文应该就是NULL的)
//传入的第一个参数是请求对象, 第二个参数是模块对象
ngx_ben_test_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_ben_test_module);

if(ctx == NULL)
{
//必须在内存池中申请对象, 这样才能保证在一个请求结束和这些资源都被释放
ctx = ngx_palloc(r->pool, sizeof(ngx_ben_test_ctx_t));
if(ctx == NULL)
return NGX_ERROR;
//把上下文结构体存起来
ngx_http_set_ctx(r, ctx, ngx_http_ben_test_module);
}

//接下里就可以使用这个上下文了
...
}
//如果Nginx多次回调ben_test模块的相应方法, 那么每次使用宏得到上下文, 继而修改再保存. 这样, 上下文就被正常使用起来了


Nginx是如何维护的:

下面看一下请求结构体中的一个变量就明白了

struct ngx_http_request_s {
...
void  **ctx;
...
}
与我们上面提到的也确实是相符合的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: