Various improvements in ngx.timer and fake connections/requests.

* optimize: reduced the pool size of a fake connection from the
  default pool size (16KB) to 128B.
* optimize: made fake requests share their connection pools.
* feature: the error logger used by ngx.timer.at handlers now
  outputs the "client: xxx, server: xxx" context info for the
  original (true) request creating the timer.
This commit is contained in:
Yichun Zhang (agentzh) 2014-11-11 22:00:48 -08:00
Родитель e6132eab93
Коммит 3085f32e70
9 изменённых файлов: 128 добавлений и 73 удалений

Просмотреть файл

@ -207,7 +207,7 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle)
ngx_destroy_pool(conf.temp_pool);
conf.temp_pool = NULL;
c = ngx_http_lua_create_fake_connection();
c = ngx_http_lua_create_fake_connection(NULL);
if (c == NULL) {
goto failed;
}
@ -261,7 +261,6 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle)
(void) lmcf->init_worker_handler(cycle->log, lmcf, lmcf->lua);
ngx_destroy_pool(r->pool);
ngx_destroy_pool(c->pool);
return NGX_OK;
@ -271,10 +270,6 @@ failed:
ngx_destroy_pool(conf.temp_pool);
}
if (r && r->pool) {
ngx_destroy_pool(r->pool);
}
if (c) {
ngx_http_lua_close_fake_connection(c);
}

Просмотреть файл

@ -102,8 +102,10 @@ ngx_http_lua_sleep_handler(ngx_event_t *ev)
return;
}
log_ctx = c->log->data;
log_ctx->current_request = r;
if (c->fd != -1) { /* not a fake connection */
log_ctx = c->log->data;
log_ctx->current_request = r;
}
coctx->cleanup = NULL;

Просмотреть файл

@ -2687,8 +2687,10 @@ ngx_http_lua_socket_tcp_handler(ngx_event_t *ev)
r = u->request;
c = r->connection;
ctx = c->log->data;
ctx->current_request = r;
if (c->fd != -1) { /* not a fake connection */
ctx = c->log->data;
ctx->current_request = r;
}
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua tcp socket handler for \"%V?%V\", wev %d", &r->uri,

Просмотреть файл

@ -1299,8 +1299,10 @@ ngx_http_lua_socket_udp_handler(ngx_event_t *ev)
r = u->request;
c = r->connection;
ctx = c->log->data;
ctx->current_request = r;
if (c->fd != -1) { /* not a fake connection */
ctx = c->log->data;
ctx->current_request = r;
}
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
"lua udp socket handler for \"%V?%V\", wev %d", &r->uri,

Просмотреть файл

@ -26,12 +26,22 @@ typedef struct {
void **srv_conf;
void **loc_conf;
ngx_pool_t *pool;
ngx_listening_t *listening;
ngx_str_t client_addr_text;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_lua_vm_state_t *vm_state;
} ngx_http_lua_timer_ctx_t;
typedef struct {
ngx_connection_t *connection;
} ngx_http_lua_timer_log_ctx_t;
static int ngx_http_lua_ngx_timer_at(lua_State *L);
static void ngx_http_lua_timer_handler(ngx_event_t *ev);
static u_char * ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf,
@ -67,7 +77,7 @@ ngx_http_lua_ngx_timer_at(lua_State *L)
ngx_http_connection_t *hc;
#endif
ngx_http_lua_timer_ctx_t *tctx;
ngx_http_lua_timer_ctx_t *tctx = NULL;
ngx_http_lua_main_conf_t *lmcf;
#if 0
ngx_http_core_main_conf_t *cmcf;
@ -201,10 +211,7 @@ ngx_http_lua_ngx_timer_at(lua_State *L)
p = ngx_alloc(sizeof(ngx_event_t) + sizeof(ngx_http_lua_timer_ctx_t),
r->connection->log);
if (p == NULL) {
lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_unref(L, -1, co_ref);
return luaL_error(L, "no memory");
goto nomem;
}
ev = (ngx_event_t *) p;
@ -223,6 +230,34 @@ ngx_http_lua_ngx_timer_at(lua_State *L)
tctx->loc_conf = r->loc_conf;
tctx->lmcf = lmcf;
tctx->pool = ngx_create_pool(128, ngx_cycle->log);
if (tctx->pool == NULL) {
goto nomem;
}
if (r->connection) {
tctx->listening = r->connection->listening;
} else {
tctx->listening = NULL;
}
if (r->connection->addr_text.len) {
tctx->client_addr_text.data = ngx_palloc(tctx->pool,
r->connection->addr_text.len);
if (tctx->client_addr_text.data == NULL) {
goto nomem;
}
ngx_memcpy(tctx->client_addr_text.data, r->connection->addr_text.data,
r->connection->addr_text.len);
tctx->client_addr_text.len = r->connection->addr_text.len;
} else {
tctx->client_addr_text.len = 0;
tctx->client_addr_text.data = NULL;
}
if (ctx && ctx->vm_state) {
tctx->vm_state = ctx->vm_state;
tctx->vm_state->count++;
@ -241,6 +276,18 @@ ngx_http_lua_ngx_timer_at(lua_State *L)
lua_pushinteger(L, 1);
return 1;
nomem:
if (tctx && tctx->pool) {
ngx_destroy_pool(tctx->pool);
}
lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_unref(L, -1, co_ref);
return luaL_error(L, "no memory");
}
@ -259,6 +306,7 @@ ngx_http_lua_timer_handler(ngx_event_t *ev)
ngx_http_lua_timer_ctx_t tctx;
ngx_http_lua_main_conf_t *lmcf;
ngx_http_core_loc_conf_t *clcf;
ngx_http_lua_timer_log_ctx_t *logctx;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua ngx.timer expired");
@ -278,12 +326,23 @@ ngx_http_lua_timer_handler(ngx_event_t *ev)
goto failed;
}
c = ngx_http_lua_create_fake_connection();
c = ngx_http_lua_create_fake_connection(tctx.pool);
if (c == NULL) {
goto failed;
}
logctx = ngx_palloc(c->pool, sizeof(ngx_http_lua_timer_log_ctx_t));
if (logctx == NULL) {
goto failed;
}
logctx->connection = c;
c->log->handler = ngx_http_lua_log_timer_error;
c->log->data = logctx;
c->listening = tctx.listening;
c->addr_text = tctx.client_addr_text;
r = ngx_http_lua_create_fake_request(c);
if (r == NULL) {
@ -402,12 +461,11 @@ failed:
ngx_http_lua_cleanup_vm(tctx.vm_state);
}
if (r && r->pool) {
ngx_destroy_pool(r->pool);
}
if (c) {
ngx_http_lua_close_fake_connection(c);
} else if (tctx.pool) {
ngx_destroy_pool(tctx.pool);
}
}
@ -416,6 +474,9 @@ static u_char *
ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf, size_t len)
{
u_char *p;
ngx_connection_t *c;
ngx_http_lua_timer_log_ctx_t *ctx;
if (log->action) {
p = ngx_snprintf(buf, len, " while %s", log->action);
@ -423,7 +484,29 @@ ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf, size_t len)
buf = p;
}
return ngx_snprintf(buf, len, ", context: ngx.timer");
ctx = log->data;
dd("ctx = %p", ctx);
p = ngx_snprintf(buf, len, ", context: ngx.timer");
len -= p - buf;
buf = p;
c = ctx->connection;
if (c->addr_text.len) {
p = ngx_snprintf(buf, len, ", client: %V", &c->addr_text);
len -= p - buf;
buf = p;
}
if (c && c->listening && c->listening->addr_text.len) {
p = ngx_snprintf(buf, len, ", server: %V", &c->listening->addr_text);
/* len -= p - buf; */
buf = p;
}
return buf;
}

Просмотреть файл

@ -3584,7 +3584,6 @@ ngx_http_lua_free_fake_request(ngx_http_request_t *r)
{
ngx_log_t *log;
ngx_http_cleanup_t *cln;
ngx_http_log_ctx_t *ctx;
log = r->connection->log;
@ -3603,15 +3602,9 @@ ngx_http_lua_free_fake_request(ngx_http_request_t *r)
}
}
/* the various request strings were allocated from r->pool */
ctx = log->data;
ctx->request = NULL;
r->request_line.len = 0;
r->connection->destroyed = 1;
ngx_destroy_pool(r->pool);
}
@ -3755,12 +3748,11 @@ ngx_http_lua_cleanup_vm(void *data)
ngx_connection_t *
ngx_http_lua_create_fake_connection(void)
ngx_http_lua_create_fake_connection(ngx_pool_t *pool)
{
ngx_log_t *log;
ngx_connection_t *c;
ngx_connection_t *saved_c = NULL;
ngx_http_log_ctx_t *logctx;
/* (we temporarily use a valid fd (0) to make ngx_get_connection happy) */
if (ngx_cycle->files) {
@ -3779,9 +3771,14 @@ ngx_http_lua_create_fake_connection(void)
c->fd = (ngx_socket_t) -1;
c->pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, c->log);
if (c->pool == NULL) {
goto failed;
if (pool) {
c->pool = pool;
} else {
c->pool = ngx_create_pool(128, c->log);
if (c->pool == NULL) {
goto failed;
}
}
log = ngx_pcalloc(c->pool, sizeof(ngx_log_t));
@ -3789,22 +3786,10 @@ ngx_http_lua_create_fake_connection(void)
goto failed;
}
logctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
if (logctx == NULL) {
goto failed;
}
dd("c pool allocated: %d", (int) (sizeof(ngx_log_t)
+ sizeof(ngx_http_log_ctx_t) + sizeof(ngx_http_request_t)));
logctx->connection = c;
logctx->request = NULL;
logctx->current_request = NULL;
c->log = log;
c->log->connection = c->number;
c->log->data = logctx;
c->log->action = NULL;
c->log->data = NULL;
c->log_error = NGX_ERROR_INFO;
@ -3832,7 +3817,6 @@ failed:
ngx_http_request_t *
ngx_http_lua_create_fake_request(ngx_connection_t *c)
{
ngx_http_log_ctx_t *logctx;
ngx_http_request_t *r;
r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
@ -3842,14 +3826,7 @@ ngx_http_lua_create_fake_request(ngx_connection_t *c)
c->requests++;
logctx = c->log->data;
logctx->request = r;
logctx->current_request = r;
r->pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, c->log);
if (r->pool == NULL) {
return NULL;
}
r->pool = c->pool;
dd("r pool allocated: %d", (int) (sizeof(ngx_http_lua_ctx_t)
+ sizeof(void *) * ngx_http_max_module + sizeof(ngx_http_cleanup_t)));
@ -3880,7 +3857,7 @@ ngx_http_lua_create_fake_request(ngx_connection_t *c)
r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
if (r->ctx == NULL) {
goto failed;
return NULL;
}
#if 0
@ -3915,14 +3892,6 @@ ngx_http_lua_create_fake_request(ngx_connection_t *c)
r->discard_body = 1;
return r;
failed:
if (r->pool) {
ngx_destroy_pool(r->pool);
}
return NULL;
}

Просмотреть файл

@ -220,7 +220,7 @@ void ngx_http_lua_release_ngx_ctx_table(ngx_log_t *log, lua_State *L,
void ngx_http_lua_cleanup_vm(void *data);
ngx_connection_t * ngx_http_lua_create_fake_connection(void);
ngx_connection_t * ngx_http_lua_create_fake_connection(ngx_pool_t *pool);
ngx_http_request_t * ngx_http_lua_create_fake_request(ngx_connection_t *c);

Просмотреть файл

@ -69,7 +69,7 @@ timer prematurely expired: true
--- error_log eval
[
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])\d*, context: ngx\.timer/,
qr/\[lua\] content_by_lua\(nginx\.conf:\d+\):\d+: elapsed: 0\.0(?:4[4-9]|5[0-6])\d*, context: ngx\.timer, client: \d+\.\d+\.\d+\.\d+, server: 0\.0\.0\.0:\d+/,
"lua ngx.timer expired",
"http lua close fake http connection",
"timer prematurely expired: false",
@ -1482,10 +1482,12 @@ registered timer
[alert]
[crit]
--- error_log
lua ngx.timer expired
http lua close fake http connection
trace: [m][f][g]
--- error_log eval
[
'lua ngx.timer expired',
'http lua close fake http connection',
qr/trace: \[m\]\[f\]\[g\], context: ngx\.timer, client: \d+\.\d+\.\d+\.\d+, server: 0\.0\.0\.0:\d+/,
]

Просмотреть файл

@ -578,7 +578,7 @@ second line received: Server: openresty
timer created
failed to connect: connection refused
--- error_log eval
qr/connect\(\) failed \(\d+: Connection refused\)/
qr/connect\(\) failed \(\d+: Connection refused\), context: ngx\.timer$/