正如标题所述,我正在为nginx开发http处理程序模块,在该模块中我想解析http请求,在后台运行任务,并在完成时想返回响应。
我尝试让http内容处理程序使用线程池来运行任务。在解析请求时,我增加了r-> main-> count,并在任务完成处理程序中将其减少了。另外,在任务完成处理程序中,我调用ngx_http_send_header和ngx_http_output_filter返回结果。这适用于10ish请求,然后阻止了nginx。它不再处理http请求。(日志中没有任何内容)。在我的开发环境中,为了简化调试,我在运行nginx时关闭了deamon,关闭了主进程,并且只有一个工作进程。
我还尝试将处理程序附加到PREACCESS和REWRITE PHASE中,然后在生成线程时返回NGX_DONE,希望nginx再次调用我的处理程序,但从未成功。
有什么想法我在做什么错吗?
谢谢!
static ngx_int_t ngx_http_image_render_handler(ngx_http_request_t *r)
{
ngx_http_image_render_ctx_t *ctx;
ngx_http_image_render_loc_conf_t *plcf;
plcf = (ngx_http_image_render_loc_conf_t*)ngx_http_get_module_loc_conf(r, ngx_http_image_render_module);
ctx = (ngx_http_image_render_ctx_t*)ngx_http_get_module_ctx(r, ngx_http_image_render_module);
if(ctx != NULL)
{
if(ctx->done != 1)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ctx already here! AGAIN");
return NGX_DONE;
}
return send_image(ctx->image_render_ctx);
}
ctx = (ngx_http_image_render_ctx_t*)ngx_pcalloc(r->pool, sizeof(ngx_http_image_render_ctx_t));
if (ctx == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "NGX_HTTP_INTERNAL_SERVER_ERROR");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ctx->request = r;
ctx->done = 0;
ngx_http_set_ctx(r, ctx, ngx_http_image_render_module);
image_render_ctx_t *image_render_ctx;
ngx_thread_task_t *task;
task = ngx_thread_task_alloc(r->pool, sizeof(image_render_ctx_t));
if (task == NULL) {
return NGX_ERROR;
}
image_render_ctx = (image_render_ctx_t*)task->ctx;
ctx->image_render_ctx = image_render_ctx;
if(ngx_http_parse_image_request(r, image_render_ctx) != NGX_OK )
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "error parsing request");
return NGX_ERROR;
}
image_render_ctx->db_util = plcf->db_util;
task->handler = image_render_func;
task->event.handler = image_render_completion;
task->event.data = image_render_ctx;
if (ngx_thread_task_post((ngx_thread_pool_t*)plcf->pool, task) != NGX_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "error posting to pool");
return NGX_ERROR;
}
r->main->count++;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "RECEIVED REQUEST!");
return NGX_DONE;
}
static int send_image(image_render_ctx_t* trc)
{
ngx_buf_t *b;
ngx_chain_t out;
u_char* image = (u_char*)trc->image_data.data();
size_t image_size = trc->image_data.length();
ngx_http_request_t *r = trc->r;
b = ngx_create_temp_buf(r->pool, image_size);
out.buf = b;
out.next = NULL;
ngx_memcpy(b->pos, image, image_size);
b->last = b->pos + image_size;
b->memory = 1;
b->last_buf = 1;
r->main->count--;
r->headers_out.content_type.len = sizeof("image/png") - 1;
r->headers_out.content_type.data = (u_char *) "image/png";
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = image_size;
ngx_http_send_header(r);
return ngx_http_output_filter(r, &out);;
}
//Attach our handler
static ngx_int_t ngx_http_image_render_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
cmcf = (ngx_http_core_main_conf_t*)ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = (ngx_http_handler_pt*)ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = (ngx_http_handler_pt)ngx_http_image_render_handler;
return NGX_OK;
}
static void
image_render_completion(ngx_event_t *ev)
{
image_render_ctx_t *ctx = (image_render_ctx_t*)ev->data;
ngx_log_error(NGX_LOG_ERR, ctx->r->connection->log, 0, "sending back image!!!");
ngx_http_image_render_ctx_t *rctx;
rctx = (ngx_http_image_render_ctx_t*)ngx_http_get_module_ctx(ctx->r, ngx_http_image_render_module);
rctx->done = 1;
}