Разбор http запроса -> запустить задачу в фоновом режиме -> когда задача завершена, вернуть ответ - PullRequest
0 голосов
/ 17 января 2019

Как видно из заголовка, я разрабатываю модуль обработчика 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...