nginx记录状态码的函数是ngx_http_reqstat_log_handler。
这个函数在ngx_http_reqstat_init函数放在log phase阶段中。
static ngx_int_t ngx_http_reqstat_init(ngx_conf_t *cf)
{
…
h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
*h = ngx_http_reqstat_log_handler;
…
}
接下来根据保存好的状态码来进行记录
static ngx_int_t ngx_http_reqstat_log_handler(ngx_http_request_t *r)
{
…
// 判断status
if (r->err_status) {
status = r->err_status;
} else if (r->headers_out.status) {
status = r->headers_out.status;
} else if (r->http_version == NGX_HTTP_VERSION_9) {
status = 9;
} else {
status = 0;
}
// 接下来根据status来进行判断,对全部的req状态码进行处理
switch (status) {
case 500:
ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_500, 1);
break;
case 502:
ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_502, 1);
break;
// 处理5xx和4xx,注意这里upstream_states是个数组,他这块选取的是最后一个元素的状态码,原因在于下方代码块
if (r->upstream_states != NULL && r->upstream_states->nelts > 0) {
ngx_http_upstream_state_t *state = r->upstream_states->elts;
status = state[r->upstream_states->nelts – 1].status;
if (status >= 400 && status < 500) {
ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_4XX, 1);
} else if (status >= 500 && status < 600) {
ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_5XX, 1);
} else if (status >= 200 && status < 300) {
ngx_http_reqstat_count(fnode, NGX_HTTP_REQSTAT_UPS_2XX, 1);
}
}
…
}
ngx_http_upstream_connect过程中,每次连接都会使用一个新的state,这是个array
void ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
…
// 从states中取出一个state,来记录后端的状态
u->state = ngx_array_push(r->upstream_states);
ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
rc = ngx_event_connect_peer(&u->peer);
// busy代表了后端断连了
if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, “no live upstreams”);
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
return;
}
// 如果connect阶段没问题,发送request
ngx_http_upstream_send_request(r, u, 1);
…
}
static void ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
ngx_uint_t do_write)
{
…
// 获取状态码
rc = ngx_http_upstream_send_request_body(r, u, do_write);
if (rc == NGX_ERROR) {
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
return;
}
// 状态码异常,使用该状态码结束请求
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
…
}
这块是判断健康检查失败如何判断出来的,是在get round robin peer的时候判断健康检查
ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
{
…
#if (NGX_HTTP_UPSTREAM_CHECK)
if (ngx_http_upstream_check_peer_down(peer->check_index)) {
goto failed;
}
#endif
failed:
return NGX_BUSY;
…
}
说会上文,ngx_http_upstream_next
static void ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
ngx_uint_t ft_type)
{
…
switch (ft_type) {
case NGX_HTTP_UPSTREAM_FT_TIMEOUT:
status = NGX_HTTP_GATEWAY_TIME_OUT;
break;
case NGX_HTTP_UPSTREAM_FT_HTTP_500:
status = NGX_HTTP_INTERNAL_SERVER_ERROR;
break;
case NGX_HTTP_UPSTREAM_FT_HTTP_403:
status = NGX_HTTP_FORBIDDEN;
break;
case NGX_HTTP_UPSTREAM_FT_HTTP_404:
status = NGX_HTTP_NOT_FOUND;
break;
/*
* NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
* never reach here
*/
default:
status = NGX_HTTP_BAD_GATEWAY;
if (status) {
u->state->status = status;
timeout = u->conf->next_upstream_timeout;
// 以这个status终结
ngx_http_upstream_finalize_request(r, u, status);
…
}
ngx_http_upstream_finalize_request中,会调用finalize request
void ngx_http_upstream_finalize_request(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_int_t rc)
{
…
// 以这个状态码结束request
ngx_http_finalize_request(r, rc);
…
}
void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{
…
// 状态码异常
if (rc >= NGX_HTTP_SPECIAL_RESPONSE
|| rc == NGX_HTTP_CREATED
|| rc == NGX_HTTP_NO_CONTENT)
{
if (rc == NGX_HTTP_CLOSE) {
ngx_http_terminate_request(r, rc);
return;
}
if (r == r->main) {
if (c->read->timer_set) {
ngx_del_timer(c->read);
}
if (c->write->timer_set) {
ngx_del_timer(c->write);
}
}
c->read->handler = ngx_http_request_handler;
c->write->handler = ngx_http_request_handler;
// 特殊状态码回调handler
ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
return;
}
…
}
ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
{
…
// err_status赋值
r->err_status = error;
// 接下来是错误页的返回
…
}
真正展示状态码计数的是这个函数
location /check_req_status {
req_status_show req_server_status;
}
static ngx_int_t ngx_http_reqstat_show_handler(ngx_http_request_t *r)
{
…
for (j = 0; j < rlcf->user_select->nelts; j++) {
if (user[j] < NGX_HTTP_REQSTAT_RSRV) {
index = user[j];
b->last = ngx_slprintf(b->last, b->end, “%uA,”,
*NGX_HTTP_REQSTAT_REQ_FIELD(node,
ngx_http_reqstat_fields[index]));
} else {
index = user[j] – NGX_HTTP_REQSTAT_RSRV;
b->last = ngx_slprintf(b->last, b->end, “%uA,”,
*NGX_HTTP_REQSTAT_REQ_FIELD(node,
NGX_HTTP_REQSTAT_EXTRA(index)));
}
}
…
}
off_t ngx_http_reqstat_fields[NGX_HTTP_REQSTAT_RSRV] = {
NGX_HTTP_REQSTAT_BYTES_IN,
NGX_HTTP_REQSTAT_BYTES_OUT,
NGX_HTTP_REQSTAT_CONN_TOTAL,
NGX_HTTP_REQSTAT_REQ_TOTAL,
NGX_HTTP_REQSTAT_2XX,
NGX_HTTP_REQSTAT_3XX,
NGX_HTTP_REQSTAT_4XX,
NGX_HTTP_REQSTAT_5XX,
NGX_HTTP_REQSTAT_OTHER_STATUS,
NGX_HTTP_REQSTAT_RT,
NGX_HTTP_REQSTAT_UPS_REQ,
NGX_HTTP_REQSTAT_UPS_RT,
NGX_HTTP_REQSTAT_UPS_TRIES,
NGX_HTTP_REQSTAT_200,
NGX_HTTP_REQSTAT_206,
NGX_HTTP_REQSTAT_302,
NGX_HTTP_REQSTAT_304,
NGX_HTTP_REQSTAT_403,
NGX_HTTP_REQSTAT_404,
NGX_HTTP_REQSTAT_416,
NGX_HTTP_REQSTAT_499,
NGX_HTTP_REQSTAT_500,
NGX_HTTP_REQSTAT_502,
NGX_HTTP_REQSTAT_503,
NGX_HTTP_REQSTAT_504,
NGX_HTTP_REQSTAT_508,
NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS,
NGX_HTTP_REQSTAT_UPS_4XX,
NGX_HTTP_REQSTAT_UPS_5XX,
NGX_HTTP_REQSTAT_UPS_2XX,
NGX_HTTP_REQSTAT_UPS_LATENCY
};
新版的nginx去掉了NGX_HTTP_REQSTAT_UPS_2XX(因为和NGX_HTTP_REQSTAT_2XX一致)
off_t ngx_http_reqstat_fields[30] = {
NGX_HTTP_REQSTAT_BYTES_IN,
NGX_HTTP_REQSTAT_BYTES_OUT,
NGX_HTTP_REQSTAT_CONN_TOTAL,
NGX_HTTP_REQSTAT_REQ_TOTAL,
NGX_HTTP_REQSTAT_2XX,
NGX_HTTP_REQSTAT_3XX,
NGX_HTTP_REQSTAT_4XX,
NGX_HTTP_REQSTAT_5XX,
NGX_HTTP_REQSTAT_OTHER_STATUS,
NGX_HTTP_REQSTAT_RT,
NGX_HTTP_REQSTAT_UPS_REQ,
NGX_HTTP_REQSTAT_UPS_RT,
NGX_HTTP_REQSTAT_UPS_TRIES,
NGX_HTTP_REQSTAT_200,
NGX_HTTP_REQSTAT_206,
NGX_HTTP_REQSTAT_302,
NGX_HTTP_REQSTAT_304,
NGX_HTTP_REQSTAT_403,
NGX_HTTP_REQSTAT_404,
NGX_HTTP_REQSTAT_416,
NGX_HTTP_REQSTAT_499,
NGX_HTTP_REQSTAT_500,
NGX_HTTP_REQSTAT_502,
NGX_HTTP_REQSTAT_503,
NGX_HTTP_REQSTAT_504,
NGX_HTTP_REQSTAT_508,
NGX_HTTP_REQSTAT_OTHER_DETAIL_STATUS,
NGX_HTTP_REQSTAT_UPS_4XX,
NGX_HTTP_REQSTAT_UPS_5XX,
NGX_HTTP_REQSTAT_UPS_LATENCY
};
lantency状态码修改
#if nginx_version >= 1009002,所以使用最新的时间结构。
typedef struct {
ngx_uint_t status;
ngx_msec_t response_time;
ngx_msec_t connect_time;
ngx_msec_t header_time;
ngx_msec_t queue_time;
off_t response_length;
off_t bytes_received;
off_t bytes_sent;
ngx_str_t *peer;
} ngx_http_upstream_state_t;
u->start_time = ngx_current_msec;
u->state->response_time = (ngx_msec_t) -1;
u->state->connect_time = (ngx_msec_t) -1;
u->state->header_time = (ngx_msec_t) -1;
而header time的时间为
static void ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
…
rc = u->process_header(r);
// 获取header time时间
u->state->header_time = ngx_current_msec – u->start_time;
…
}
来源:freebuf.com 2020-11-29 18:18:28 by: stan1y
请登录后发表评论
注册