Как видно из заголовка, я разрабатываю модуль обработчика http для nginx, в котором я хочу проанализировать 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;
}