From 069aa4cd73b8a3b98d7807d360d668521f536376 Mon Sep 17 00:00:00 2001 From: djq <1953187027@qq.com> Date: Tue, 2 Jul 2024 16:35:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=A8=E6=96=B0=E7=9A=84=E4=B8=BB=E5=8A=A8?= =?UTF-8?q?=E6=8E=A2=E6=B5=8B=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ngx_http_upstream_check_module.c | 364 ++++++++++++++---- 1 file changed, 279 insertions(+), 85 deletions(-) diff --git a/src/ngx_http_upstream_check_module/ngx_http_upstream_check_module.c b/src/ngx_http_upstream_check_module/ngx_http_upstream_check_module.c index 670eae3..8946541 100644 --- a/src/ngx_http_upstream_check_module/ngx_http_upstream_check_module.c +++ b/src/ngx_http_upstream_check_module/ngx_http_upstream_check_module.c @@ -1,8 +1,7 @@ - #include #include "ngx_http_upstream_check_module.h" - - +#include +#include typedef struct ngx_http_upstream_check_peer_s ngx_http_upstream_check_peer_t; typedef struct ngx_http_upstream_check_srv_conf_s ngx_http_upstream_check_srv_conf_t; @@ -10,6 +9,8 @@ typedef struct ngx_http_upstream_check_srv_conf_s #pragma pack(push, 1) +ngx_str_t sendTime; +ngx_str_t receiveTime; typedef struct { u_char major; u_char minor; @@ -123,6 +124,8 @@ struct ngx_http_upstream_check_peer_s { /*peer关键配置类:包括一组回 ngx_event_t check_ev; /*关键数据结构:check event*/ ngx_event_t check_timeout_ev; /*关键数据结构: check timeout event*/ ngx_peer_connection_t pc; + ngx_str_t *last_receive_time;// 尝试添加,最后接受到数据返回的时间 + ngx_str_t *last_check_time;//尝试添加,最后发送探测数据包进行检查的时间 void *check_data; ngx_event_handler_pt send_handler; /*TODO: ???*/ @@ -335,8 +338,8 @@ static ngx_int_t ngx_http_upstream_check_peek_one_byte(ngx_connection_t *c); static void ngx_http_upstream_check_begin_handler(ngx_event_t *event); static void ngx_http_upstream_check_connect_handler(ngx_event_t *event); -static void ngx_http_upstream_check_peek_handler(ngx_event_t *event); - +static void ngx_http_upstream_check_peek_handler1(ngx_event_t *event); +static void ngx_http_upstream_check_peek_handler2(ngx_event_t *event); static void ngx_http_upstream_check_send_handler(ngx_event_t *event); static void ngx_http_upstream_check_recv_handler(ngx_event_t *event); @@ -485,7 +488,7 @@ static ngx_conf_bitmask_t ngx_check_http_expect_alive_masks[] = { { ngx_null_string, 0 } }; - +//主动检查指令 static ngx_command_t ngx_http_upstream_check_commands[] = { { ngx_string("check"), @@ -636,15 +639,15 @@ static char ngx_ajp_cpong_packet[] = { 0x41, 0x42, 0x00, 0x01, NGX_AJP_CPONG }; -/* YEP! 核心配置:支持tcp\http\fastcgi\ssl_hello\mysql\ajp多种协议,并设置不同的回调函数*/ +/* 核心配置:支持tcp\http\fastcgi\ssl_hello\mysql\ajp多种协议,并设置不同的回调函数*/ static ngx_check_conf_t ngx_check_types[] = { { NGX_HTTP_CHECK_TCP, - ngx_string("tcp"), + ngx_string("tcp"),//TCP协议 ngx_null_string, 0, - ngx_http_upstream_check_peek_handler, - ngx_http_upstream_check_peek_handler, + ngx_http_upstream_check_peek_handler1, + ngx_http_upstream_check_peek_handler2, NULL, NULL, NULL, @@ -652,7 +655,7 @@ static ngx_check_conf_t ngx_check_types[] = { 1 }, { NGX_HTTP_CHECK_HTTP, - ngx_string("http"), + ngx_string("http"),//HTTP协议 ngx_string("GET / HTTP/1.0\r\n\r\n"), NGX_CONF_BITMASK_SET | NGX_CHECK_HTTP_2XX | NGX_CHECK_HTTP_3XX, ngx_http_upstream_check_send_handler, @@ -664,7 +667,7 @@ static ngx_check_conf_t ngx_check_types[] = { 1 }, { NGX_HTTP_CHECK_HTTP, - ngx_string("fastcgi"), + ngx_string("fastcgi"),//fastcgi协议 ngx_null_string, 0, ngx_http_upstream_check_send_handler, @@ -676,7 +679,7 @@ static ngx_check_conf_t ngx_check_types[] = { 0 }, { NGX_HTTP_CHECK_SSL_HELLO, - ngx_string("ssl_hello"), + ngx_string("ssl_hello"),//SSl协议 ngx_string(sslv3_client_hello_pkt), 0, ngx_http_upstream_check_send_handler, @@ -688,7 +691,7 @@ static ngx_check_conf_t ngx_check_types[] = { 0 }, { NGX_HTTP_CHECK_MYSQL, - ngx_string("mysql"), + ngx_string("mysql"),//mysql数据库类型 ngx_null_string, 0, ngx_http_upstream_check_send_handler, @@ -700,7 +703,7 @@ static ngx_check_conf_t ngx_check_types[] = { 0 }, { NGX_HTTP_CHECK_AJP, - ngx_string("ajp"), + ngx_string("ajp"),//ajp协议 ngx_string(ngx_ajp_cping_packet), 0, ngx_http_upstream_check_send_handler, @@ -759,7 +762,9 @@ static ngx_check_status_command_t ngx_check_status_commands[] = { static ngx_uint_t ngx_http_upstream_check_shm_generation = 0; static ngx_http_upstream_check_peers_t *check_peers_ctx = NULL; /* 最核心的数据结构:保存了后端服务器所有相关数据 */ - +/** + * 用于设置和维护对目标服务器的健康检查 + */ ngx_uint_t ngx_http_upstream_check_add_peer(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us, ngx_addr_t *peer_addr) @@ -769,25 +774,29 @@ ngx_http_upstream_check_add_peer(ngx_conf_t *cf, ngx_http_upstream_check_srv_conf_t *ucscf; ngx_http_upstream_check_main_conf_t *ucmcf; + //检查服务器的配置是否正确 if (us->srv_conf == NULL) { return NGX_ERROR; } - ucscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_check_module); - + ucscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_check_module);//获取检查间隔 + + //没有检查间隔,即出错 if(ucscf->check_interval == 0) { return NGX_ERROR; } + //获取nginx.conf文件中的模块配置,包含了共享的配置信息 ucmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_check_module); peers = ucmcf->peers; - + + //进行内存分配 peer = ngx_array_push(&peers->peers); if (peer == NULL) { return NGX_ERROR; } - + //初始化新的检查点 ngx_memzero(peer, sizeof(ngx_http_upstream_check_peer_t)); peer->index = peers->peers.nelts - 1; @@ -795,6 +804,7 @@ ngx_http_upstream_check_add_peer(ngx_conf_t *cf, peer->upstream_name = &us->host; peer->peer_addr = peer_addr; + //对端口进行处理 if (ucscf->port) { peer->check_peer_addr = ngx_pcalloc(cf->pool, sizeof(ngx_addr_t)); if (peer->check_peer_addr == NULL) { @@ -815,10 +825,10 @@ ngx_http_upstream_check_add_peer(ngx_conf_t *cf, peers->checksum += ngx_murmur_hash2(peer_addr->name.data, peer_addr->name.len); - return peer->index; + return peer->index;//返回刚刚添加的检查点的索引 } - +/*修改给定地址src的端口号,并且将 结果存放在 dst中,用来进行网络地址和端口的转换 */ static ngx_int_t ngx_http_upstream_check_addr_change_port(ngx_pool_t *pool, ngx_addr_t *dst, ngx_addr_t *src, ngx_uint_t port) @@ -831,13 +841,14 @@ ngx_http_upstream_check_addr_change_port(ngx_pool_t *pool, ngx_addr_t *dst, #endif dst->socklen = src->socklen; - dst->sockaddr = ngx_palloc(pool, dst->socklen); + dst->sockaddr = ngx_palloc(pool, dst->socklen);//为dist(存放修改后的地址) 分配足够的内存空间 if (dst->sockaddr == NULL) { return NGX_ERROR; } - ngx_memcpy(dst->sockaddr, src->sockaddr, dst->socklen); + ngx_memcpy(dst->sockaddr, src->sockaddr, dst->socklen);//复制src中的内存地址 + /* 地址转换为字符串 */ switch (dst->sockaddr->sa_family) { case AF_INET: @@ -872,71 +883,79 @@ ngx_http_upstream_check_addr_change_port(ngx_pool_t *pool, ngx_addr_t *dst, #else len = ngx_sock_ntop(dst->sockaddr, p, len, 1); #endif - + /*重新设置地址字符串的属性 */ dst->name.len = len; dst->name.data = p; - return NGX_OK; + return NGX_OK;//表示操作成功 } - +/*检查Nginx配置中的某个服务器检查点状态是否被标记为down */ ngx_uint_t ngx_http_upstream_check_peer_down(ngx_uint_t index) { ngx_http_upstream_check_peer_t *peer; - + // 检查全局上下文是否已初始化,以及索引是否在有效范围内 if (check_peers_ctx == NULL || index >= check_peers_ctx->peers.nelts) { return 0; } - peer = check_peers_ctx->peers.elts; + peer = check_peers_ctx->peers.elts;//访问全局上下文中的对等体数组 return (peer[index].shm->down); } /* TODO: this interface can count each peer's busyness */ +/** + * 用于获取对HTTP流量服务器组进行检查的对等体(peer)信息 + * 对等体:网络中地位相等的节点或实体。这里指 服务器组中的一系列服务器 + * @Author dongjiaqi + * @CreateTime 2024.6.1 + */ void ngx_http_upstream_check_get_peer(ngx_uint_t index) { ngx_http_upstream_check_peer_t *peer; - + // 检查全局上下文是否已初始化,以及索引是否在有效范围内 if (check_peers_ctx == NULL || index >= check_peers_ctx->peers.nelts) { return; } - peer = check_peers_ctx->peers.elts; + peer = check_peers_ctx->peers.elts;//访问全局上下文中的对等体数组 - ngx_shmtx_lock(&peer[index].shm->mutex); + ngx_shmtx_lock(&peer[index].shm->mutex);//锁定指定对等体的共享内存区的互斥锁 - peer[index].shm->busyness++; - peer[index].shm->access_count++; + peer[index].shm->busyness++;//增加忙碌度(busyness)计数器 + peer[index].shm->access_count++;//增加访问次数 - ngx_shmtx_unlock(&peer[index].shm->mutex); + ngx_shmtx_unlock(&peer[index].shm->mutex);// 解锁互斥锁 } - - +/**用于释放对HTTP流量服务器组进行检查的对等体(peer)的资源 + * @Author dongjiaqi + * @CreateTime 2024.6.1 + */ void ngx_http_upstream_check_free_peer(ngx_uint_t index) { ngx_http_upstream_check_peer_t *peer; - + // 检查全局上下文是否已初始化,以及索引是否在有效范围内 if (check_peers_ctx == NULL || index >= check_peers_ctx->peers.nelts) { return; } - peer = check_peers_ctx->peers.elts; - - ngx_shmtx_lock(&peer[index].shm->mutex); + peer = check_peers_ctx->peers.elts;// 访问全局上下文中的对等体数组 + ngx_shmtx_lock(&peer[index].shm->mutex);// 锁定共享内存区的互斥锁 + // 检查该对等体是否正在忙碌(busyness > 0) if (peer[index].shm->busyness > 0) { - peer[index].shm->busyness--; + peer[index].shm->busyness--;// 如果正在忙碌,则减少忙碌度计数器 } - ngx_shmtx_unlock(&peer[index].shm->mutex); + ngx_shmtx_unlock(&peer[index].shm->mutex);// 解锁互斥锁 } - +/*为服务器检查功能设置定时器 */ static ngx_int_t ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle) { @@ -958,18 +977,20 @@ ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle) if (peers_shm == NULL) { return NGX_OK; } - + + //使用 ngx_log_debug2 记录调试信息,包括共享内存名称和对等体数量。 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "http check upstream init_process, shm_name: %V, " "peer number: %ud", &peers->check_shm_name, peers->peers.nelts); - srandom(ngx_pid); + srandom(ngx_pid);//使用 srandom 设置随机数种子,以便为定时器生成随机的开始时间。 peer = peers->peers.elts; peer_shm = peers_shm->peers; + //遍历 peers 数组,为每个对等体设置定时器和事件处理函数。 for (i = 0; i < peers->peers.nelts; i++) { peer[i].shm = &peer_shm[i]; @@ -979,7 +1000,7 @@ ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle) peer[i].check_ev.timer_set = 0; peer[i].check_timeout_ev.handler = - ngx_http_upstream_check_timeout_handler; /* 这个应该是处理超时event的回调函数? */ + ngx_http_upstream_check_timeout_handler; /* 处理超时event的回调函数 */ peer[i].check_timeout_ev.log = cycle->log; peer[i].check_timeout_ev.data = &peer[i]; peer[i].check_timeout_ev.timer_set = 0; @@ -987,6 +1008,7 @@ ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle) ucscf = peer[i].conf; cf = ucscf->check_type_conf; + //如果配置需要,为每个对等体创建内存池。 if (cf->need_pool) { peer[i].pool = ngx_create_pool(ngx_pagesize, cycle->log); if (peer[i].pool == NULL) { @@ -1002,19 +1024,19 @@ ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle) peer[i].reinit = cf->reinit; /* - * We add a random start time here, since we don't want to trigger - * the check events too close to each other at the beginning. + * 为了避免所有检查事件同时开始,为每个定时器添加一个随机的开始时间 */ delay = ucscf->check_interval > 1000 ? ucscf->check_interval : 1000; t = ngx_random() % delay; + //使用 ngx_add_timer 函数为每个对等体的检查事件添加定时器 ngx_add_timer(&peer[i].check_ev, t); } return NGX_OK; } -/* 处理check相关event*/ +/* 处理check相关event(begin)*/ static void ngx_http_upstream_check_begin_handler(ngx_event_t *event) { @@ -1073,11 +1095,10 @@ ngx_http_upstream_check_begin_handler(ngx_event_t *event) } else if (interval >= (ucscf->check_interval << 4)) { /* - * If the check peer has been untouched for 2^4 times of - * the check interval, activate the current timer. - * Sometimes, the checking process may disappear - * in some circumstances, and the clean event will never - * be triggered. + * 如果检查对等体在 2^4次检查间隔时间内未被触及, + * 就激活当前的定时器; + * 在某些情况下,检查进程可能会消失, + * 而且清理事件永远不会被触发; */ peer->shm->owner = ngx_pid; peer->shm->access_time = ngx_current_msec; @@ -1090,7 +1111,7 @@ ngx_http_upstream_check_begin_handler(ngx_event_t *event) } } - +/* 处理check相关event(connect)*/ static void ngx_http_upstream_check_connect_handler(ngx_event_t *event) { @@ -1159,6 +1180,9 @@ upstream_check_connect_done: } } +/** + *用于检查数据是否可用而不影响实际的数据流 + */ static ngx_int_t ngx_http_upstream_check_peek_one_byte(ngx_connection_t *c) { @@ -1166,9 +1190,10 @@ ngx_http_upstream_check_peek_one_byte(ngx_connection_t *c) ngx_int_t n; ngx_err_t err; - n = recv(c->fd, buf, 1, MSG_PEEK); + n = recv(c->fd, buf, 1, MSG_PEEK);//接收数据 err = ngx_socket_errno; + //使用 ngx_log_debug2 记录调试信息,包括接收到的数据字节数和文件描述符 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, err, "http check upstream recv(): %i, fd: %d", n, c->fd); @@ -1180,12 +1205,13 @@ ngx_http_upstream_check_peek_one_byte(ngx_connection_t *c) } } +/*事件处理函数,处理服务器检查中的事件,对应tcp协议 */ static void -ngx_http_upstream_check_peek_handler(ngx_event_t *event) +ngx_http_upstream_check_peek_handler1(ngx_event_t *event) { ngx_connection_t *c; ngx_http_upstream_check_peer_t *peer; - + if (ngx_http_upstream_check_need_exit()) { return; } @@ -1193,20 +1219,66 @@ ngx_http_upstream_check_peek_handler(ngx_event_t *event) c = event->data; peer = c->data; + //状态更新 if (ngx_http_upstream_check_peek_one_byte(c) == NGX_OK) { ngx_http_upstream_check_status_update(peer, 1); - + } else { c->error = 1; ngx_http_upstream_check_status_update(peer, 0); } + + // 首先,确保 ngx_time_update 已经被调用,以便更新时间缓存。 + ngx_time_init(); + ngx_time_update(); + // 然后,将 ngx_cached_http_time 的值复制到 sendTime 变量中。 + sendTime.data = ngx_cached_http_time.data; + sendTime.len = ngx_cached_http_time.len; + ngx_http_upstream_check_clean_event(peer); ngx_http_upstream_check_finish_handler(event); + } +/*事件处理函数,处理服务器检查中的事件,对应tcp协议 */ +static void +ngx_http_upstream_check_peek_handler2(ngx_event_t *event) +{ + ngx_connection_t *c; + ngx_http_upstream_check_peer_t *peer; + + if (ngx_http_upstream_check_need_exit()) { + return; + } + + c = event->data; + peer = c->data; + //状态更新 + if (ngx_http_upstream_check_peek_one_byte(c) == NGX_OK) { + ngx_http_upstream_check_status_update(peer, 1); + + } else { + c->error = 1; + ngx_http_upstream_check_status_update(peer, 0); + } + + ngx_http_upstream_check_clean_event(peer); + + ngx_http_upstream_check_finish_handler(event); + // 首先,确保 ngx_time_update 已经被调用,以便更新时间缓存。 + ngx_time_init(); + ngx_time_update(); + + // 然后,将 ngx_cached_http_time 的值复制到 receiveTime 变量中。 + receiveTime.data = ngx_cached_http_time.data; + receiveTime.len = ngx_cached_http_time.len; + +} + +/*事件处理函数,用于处理连接上的废弃数据 */ static void ngx_http_upstream_check_discard_handler(ngx_event_t *event) { @@ -1256,14 +1328,14 @@ ngx_http_upstream_check_discard_handler(ngx_event_t *event) ngx_http_upstream_check_clean_event(peer); } - +//直接返回的空函数 static void ngx_http_upstream_check_dummy_handler(ngx_event_t *event) { return; } - +/*发送检查探测数据包的任务处理器*/ static void ngx_http_upstream_check_send_handler(ngx_event_t *event) { @@ -1279,8 +1351,10 @@ ngx_http_upstream_check_send_handler(ngx_event_t *event) c = event->data; peer = c->data; + //用日志记录发送了http健康检查数据 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http check send."); + //日志记录检查失败 if (c->pool == NULL) { ngx_log_error(NGX_LOG_ERR, event->log, 0, "check pool NULL with peer: %V ", @@ -1289,6 +1363,7 @@ ngx_http_upstream_check_send_handler(ngx_event_t *event) goto check_send_fail; } + //检查到服务器状态错误,日志记录检查失败 if (peer->state != NGX_HTTP_CHECK_CONNECT_DONE) { if (ngx_handle_write_event(c->write, 0) != NGX_OK) { @@ -1348,6 +1423,15 @@ ngx_http_upstream_check_send_handler(ngx_event_t *event) } if (ctx->send.pos == ctx->send.last) { + + // 首先,确保 ngx_time_update 已经被调用,以便更新时间缓存。 + ngx_time_init(); + ngx_time_update(); + + // 然后,将 ngx_cached_http_time 的值复制到 TIME 变量中。 + sendTime.data = ngx_cached_http_time.data; + sendTime.len = ngx_cached_http_time.len; + // ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http check send done."); peer->state = NGX_HTTP_CHECK_SEND_DONE; c->requests++; @@ -1360,7 +1444,7 @@ check_send_fail: ngx_http_upstream_check_clean_event(peer); } - +/*用于接收服务器返回响应数据的任务处理器 */ static void ngx_http_upstream_check_recv_handler(ngx_event_t *event) { @@ -1421,7 +1505,15 @@ ngx_http_upstream_check_recv_handler(ngx_event_t *event) } size = c->recv(c, ctx->recv.last, n); - + + // 首先,确保 ngx_time_update 已经被调用,以便更新时间缓存。 + ngx_time_init(); + ngx_time_update(); + + // 然后,将 ngx_cached_http_time 的值复制到 receiveTime 变量中。 + receiveTime.data = ngx_cached_http_time.data; + receiveTime.len = ngx_cached_http_time.len; + #if (NGX_DEBUG) { ngx_err_t err; @@ -1488,7 +1580,7 @@ check_recv_fail: ngx_http_upstream_check_clean_event(peer); } - +//初始化 HTTP 检查的上下文 static ngx_int_t ngx_http_upstream_check_http_init(ngx_http_upstream_check_peer_t *peer) { @@ -1511,7 +1603,7 @@ ngx_http_upstream_check_http_init(ngx_http_upstream_check_peer_t *peer) return NGX_OK; } - +//暂停 HTTP 检查 static ngx_int_t ngx_http_upstream_check_http_parse(ngx_http_upstream_check_peer_t *peer) { @@ -1572,7 +1664,7 @@ ngx_http_upstream_check_http_parse(ngx_http_upstream_check_peer_t *peer) return NGX_OK; } - +//使用fastcgi端口的检查处理器 static ngx_int_t ngx_http_upstream_check_fastcgi_process_record( ngx_http_upstream_check_ctx_t *ctx, ngx_buf_t *b, ngx_http_status_t *status) @@ -1675,7 +1767,7 @@ ngx_http_upstream_check_fastcgi_process_record( return NGX_AGAIN; } - +//用于 基于fastcg端口的检查 的暂停 static ngx_int_t ngx_http_upstream_check_fastcgi_parse(ngx_http_upstream_check_peer_t *peer) { @@ -1837,6 +1929,10 @@ ngx_http_upstream_check_fastcgi_parse(ngx_http_upstream_check_peer_t *peer) } +/** + *用于在暂停fastcgi检查之后: + *能够获取当前健康检查状态 + */ static ngx_int_t ngx_http_upstream_check_parse_fastcgi_status(ngx_http_upstream_check_ctx_t *ctx, ngx_buf_t *b, ngx_http_status_t *status) @@ -2089,7 +2185,7 @@ header_done: return NGX_OK; } - +//获取http服务器健康检查状态 static ngx_int_t ngx_http_upstream_check_parse_status_line(ngx_http_upstream_check_ctx_t *ctx, ngx_buf_t *b, ngx_http_status_t *status) @@ -2282,7 +2378,7 @@ done: return NGX_OK; } - +//重新初始化http健康检查 static void ngx_http_upstream_check_http_reinit(ngx_http_upstream_check_peer_t *peer) { @@ -2300,7 +2396,7 @@ ngx_http_upstream_check_http_reinit(ngx_http_upstream_check_peer_t *peer) ngx_memzero(&ctx->status, sizeof(ngx_http_status_t)); } - +//利用ssl_hello通信进行健康检查的初始化 static ngx_int_t ngx_http_upstream_check_ssl_hello_init(ngx_http_upstream_check_peer_t *peer) { @@ -2320,7 +2416,7 @@ ngx_http_upstream_check_ssl_hello_init(ngx_http_upstream_check_peer_t *peer) } -/* a rough check of server ssl_hello responses */ +//利用ssl_hello通信进行健康检查的暂停 static ngx_int_t ngx_http_upstream_check_ssl_hello_parse(ngx_http_upstream_check_peer_t *peer) { @@ -2355,7 +2451,7 @@ ngx_http_upstream_check_ssl_hello_parse(ngx_http_upstream_check_peer_t *peer) return NGX_OK; } - +//利用ssl_hello通信进行健康检查的重新初始化 static void ngx_http_upstream_check_ssl_hello_reinit(ngx_http_upstream_check_peer_t *peer) { @@ -2370,6 +2466,7 @@ ngx_http_upstream_check_ssl_hello_reinit(ngx_http_upstream_check_peer_t *peer) } +//利用mysql通信进行健康检查的初始化 static ngx_int_t ngx_http_upstream_check_mysql_init(ngx_http_upstream_check_peer_t *peer) { @@ -2389,7 +2486,7 @@ ngx_http_upstream_check_mysql_init(ngx_http_upstream_check_peer_t *peer) } -/* a rough check of mysql greeting responses */ +//利用mysql通信进行健康检查的暂停 static ngx_int_t ngx_http_upstream_check_mysql_parse(ngx_http_upstream_check_peer_t *peer) { @@ -2420,6 +2517,7 @@ ngx_http_upstream_check_mysql_parse(ngx_http_upstream_check_peer_t *peer) } +//利用mysql通信进行健康检查的重新初始化 static void ngx_http_upstream_check_mysql_reinit(ngx_http_upstream_check_peer_t *peer) { @@ -2433,7 +2531,7 @@ ngx_http_upstream_check_mysql_reinit(ngx_http_upstream_check_peer_t *peer) ctx->recv.pos = ctx->recv.last = ctx->recv.start; } - +/*用于初始化 AJP (Apache JServ Protocol) 检查的发送和接收缓冲区的函数*/ static ngx_int_t ngx_http_upstream_check_ajp_init(ngx_http_upstream_check_peer_t *peer) { @@ -2453,6 +2551,7 @@ ngx_http_upstream_check_ajp_init(ngx_http_upstream_check_peer_t *peer) } +/*用于解析 AJP (Apache JServ Protocol) 协议的响应数据的函数*/ static ngx_int_t ngx_http_upstream_check_ajp_parse(ngx_http_upstream_check_peer_t *peer) { @@ -2489,6 +2588,7 @@ ngx_http_upstream_check_ajp_parse(ngx_http_upstream_check_peer_t *peer) } +/*用于重置和重新初始化 AJP (Apache JServ Protocol) 上游检查对等体(peer)的特定检查数据的函数*/ static void ngx_http_upstream_check_ajp_reinit(ngx_http_upstream_check_peer_t *peer) { @@ -2503,6 +2603,7 @@ ngx_http_upstream_check_ajp_reinit(ngx_http_upstream_check_peer_t *peer) } +/*用于根据检查结果更新检查对等体的状态*/ static void ngx_http_upstream_check_status_update(ngx_http_upstream_check_peer_t *peer, ngx_int_t result) @@ -2534,7 +2635,7 @@ ngx_http_upstream_check_status_update(ngx_http_upstream_check_peer_t *peer, peer->shm->access_time = ngx_current_msec; } - +/*清理与服务器检查 对等体(peer)相关的事件和资源*/ static void ngx_http_upstream_check_clean_event(ngx_http_upstream_check_peer_t *peer) { @@ -2575,7 +2676,7 @@ ngx_http_upstream_check_clean_event(ngx_http_upstream_check_peer_t *peer) peer->shm->owner = NGX_INVALID_PID; } - +/*用于检查Nginx是否需要退出或重启。它检查全局变量ngx_terminate、ngx_exiting或ngx_quit的状态*/ static void ngx_http_upstream_check_timeout_handler(ngx_event_t *event) { @@ -2597,6 +2698,7 @@ ngx_http_upstream_check_timeout_handler(ngx_event_t *event) } +/*这两个函数是Nginx上游服务器检查模块的一部分,用于处理Nginx关闭或重启时的相关清理工作*/ static void ngx_http_upstream_check_finish_handler(ngx_event_t *event) { @@ -2606,6 +2708,7 @@ ngx_http_upstream_check_finish_handler(ngx_event_t *event) } +/*用于判断Nginx是否需要退出或重启,并在需要时清理上游服务器检查模块的事件*/ static ngx_int_t ngx_http_upstream_check_need_exit() { @@ -2618,6 +2721,7 @@ ngx_http_upstream_check_need_exit() } +/*清除Nginx 对服务器检查模块中所有相关的定时器和事件*/ static void ngx_http_upstream_check_clear_all_events() { @@ -2664,6 +2768,11 @@ ngx_http_upstream_check_clear_all_events() } +/** + *Nginx HTTP模块的请求处理函数,ngx_http_upstream_check_status_handler, + *用于处理HTTP请求并返回对服务器检查的状态 + *允许用户通过HTTP接口查询服务器的健康状态 + */ static ngx_int_t ngx_http_upstream_check_status_handler(ngx_http_request_t *r) { @@ -2752,6 +2861,7 @@ ngx_http_upstream_check_status_handler(ngx_http_request_t *r) } +/*根据提供的格式名称字符串,在Nginx的配置中查找对应的状态检查输出格式,并将其设置到状态检查的上下文中。*/ static void ngx_http_upstream_check_status_parse_args(ngx_http_request_t *r, ngx_http_upstream_check_status_ctx_t *ctx) @@ -2788,6 +2898,7 @@ ngx_http_upstream_check_status_parse_args(ngx_http_request_t *r, } +/*用于处理Nginx配置指令中的格式参数,并设置状态检查的输出格式*/ static ngx_int_t ngx_http_upstream_check_status_command_format( ngx_http_upstream_check_status_ctx_t *ctx, ngx_str_t *value) @@ -2801,6 +2912,11 @@ ngx_http_upstream_check_status_command_format( } +/** + *根据提供的字符串参数,设置Nginx上游服务器检查的状态检查标志。 + *它允许用户指定只检查状态为"down"的服务器,或者状态为"up"的服务器,或者两者都检查(如果两个条件都不满足,则认为是无效输入)。 + *这种功能可以用于定制化地监控和报告上游服务器的状态。 + */ static ngx_int_t ngx_http_upstream_check_status_command_status( ngx_http_upstream_check_status_ctx_t *ctx, ngx_str_t *value) @@ -3055,6 +3171,7 @@ b->last = ngx_snprintf(b->last, b->end - b->last, } +/*用于将Nginx上游服务器检查的状态格式化为CSV(逗号分隔值)格式*/ static void ngx_http_upstream_check_status_csv_format(ngx_buf_t *b, ngx_http_upstream_check_peers_t *peers, ngx_uint_t flag) @@ -3092,6 +3209,7 @@ ngx_http_upstream_check_status_csv_format(ngx_buf_t *b, } +/*用于将Nginx 对服务器检查得到的状态格式化为JSON格式的字符串 */ static void ngx_http_upstream_check_status_json_format(ngx_buf_t *b, ngx_http_upstream_check_peers_t *peers, ngx_uint_t flag) @@ -3131,7 +3249,16 @@ ngx_http_upstream_check_status_json_format(ngx_buf_t *b, last = peers->peers.nelts - 1; for (i = 0; i < peers->peers.nelts; i++) { - + // 首先,确保 ngx_time_update 已经被调用,以便更新时间缓存。 + //ngx_time_init(); + //ngx_time_update(); + + // 然后,将 ngx_cached_http_time 的值复制到 sendTime 变量中。 + //sendTime.data = ngx_cached_http_time.data; + //sendTime.len = ngx_cached_http_time.len; + + peer[i].last_check_time=&sendTime; + if (flag & NGX_CHECK_STATUS_DOWN) { if (!peer[i].shm->down) { @@ -3144,7 +3271,11 @@ ngx_http_upstream_check_status_json_format(ngx_buf_t *b, continue; } } - + if(peer[i].shm->down &&peer[i].shm->rise_count==0){ + receiveTime.data = 0; + receiveTime.len = 0; + } + peer[i].last_receive_time=&receiveTime; b->last = ngx_snprintf(b->last, b->end - b->last, " {\"index\": %ui, " "\"upstream\": \"%V\", " @@ -3153,7 +3284,9 @@ ngx_http_upstream_check_status_json_format(ngx_buf_t *b, "\"rise\": %ui, " "\"fall\": %ui, " "\"type\": \"%V\", " - "\"port\": %ui}" + "\"port\": %ui," + "\"last_receive_time\": \"%V\"," + "\"last_check_time\": \"%V\"}" "%s\n", i, peer[i].upstream_name, @@ -3163,6 +3296,8 @@ ngx_http_upstream_check_status_json_format(ngx_buf_t *b, peer[i].shm->fall_count, &peer[i].conf->check_type_conf->name, peer[i].conf->port, + peer[i].last_receive_time, + peer[i].last_check_time, (i == last) ? "" : ","); } @@ -3174,6 +3309,10 @@ ngx_http_upstream_check_status_json_format(ngx_buf_t *b, } +/** + *用于根据提供的字符串(str)在Nginx配置中查找对应的检查类型配置。 + *这个函数遍历一个预定义的检查类型数组,寻找一个名称与提供字符串匹配的检查类型 + */ static ngx_check_conf_t * ngx_http_get_check_type_conf(ngx_str_t *str) { @@ -3199,6 +3338,7 @@ ngx_http_get_check_type_conf(ngx_str_t *str) return NULL; } + /*check指令的conf handler,已经被注册到command数组中*/ static char * ngx_http_upstream_check(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -3345,6 +3485,10 @@ invalid_check_parameter: } +/** + *在Nginx配置文件中处理ngx_http_upstream_check_keepalive_requests指令; + *允许管理员指定在服务器检查中,一个keepalive连接可以发送的请求的最大数量 + */ static char * ngx_http_upstream_check_keepalive_requests(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -3369,6 +3513,10 @@ ngx_http_upstream_check_keepalive_requests(ngx_conf_t *cf, ngx_command_t *cmd, } +/** + *用于设置HTTP上游服务器检查(upstream check)的发送内容。 + *这个函数允许管理员在Nginx配置文件中指定当Nginx对上游服务器进行健康检查时,通过HTTP发送的请求数据。 + */ static char * ngx_http_upstream_check_http_send(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -3387,6 +3535,7 @@ ngx_http_upstream_check_http_send(ngx_conf_t *cf, ngx_command_t *cmd, } +/**用于设置FastCGI类型的 服务器检查发送的参数对 */ static char * ngx_http_upstream_check_fastcgi_params(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -3416,6 +3565,7 @@ ngx_http_upstream_check_fastcgi_params(ngx_conf_t *cf, ngx_command_t *cmd, } +/**用于设置在HTTP检查中期望 服务器返回的存活状态码 */ static char * ngx_http_upstream_check_http_expect_alive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) @@ -3466,6 +3616,7 @@ ngx_http_upstream_check_http_expect_alive(ngx_conf_t *cf, ngx_command_t *cmd, } +/*用于设置对服务器进行健康检查的模块 使用的共享内存区域的大小*/ static char * ngx_http_upstream_check_shm_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -3489,6 +3640,7 @@ ngx_http_upstream_check_shm_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } +/*用于根据给定的字符串查找检查状态格式配置的函数*/ static ngx_check_status_conf_t * ngx_http_get_check_status_format_conf(ngx_str_t *str) { @@ -3515,6 +3667,7 @@ ngx_http_get_check_status_format_conf(ngx_str_t *str) } +/*设置特定location的handler来处理HTTP请求,并配置检查状态的格式*/ static char * ngx_http_upstream_check_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -3544,7 +3697,10 @@ ngx_http_upstream_check_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } -/* 创建main配置: 创建三类内存空间:ngx_http_upstream_check_main_conf_t, ngx_http_upstream_check_peers_t*/ +/** + *创建main配置: + *创建三类内存空间:ngx_http_upstream_check_main_conf_t, ngx_http_upstream_check_peers_t + */ static void * ngx_http_upstream_check_create_main_conf(ngx_conf_t *cf) { @@ -3572,7 +3728,10 @@ ngx_http_upstream_check_create_main_conf(ngx_conf_t *cf) return ucmcf; } - +/** + *Nginx中用于创建FastCGI请求的函数 + *用于生成 对于服务器继续健康检查的FastCGI请求 + */ static ngx_buf_t * ngx_http_upstream_check_create_fastcgi_request(ngx_pool_t *pool, ngx_str_t *params, ngx_uint_t num) @@ -3678,7 +3837,10 @@ ngx_http_upstream_check_create_fastcgi_request(ngx_pool_t *pool, return b; } -/* 初始化main configuration*/ +/** + *用于初始化主配置段 + *初始化main configuration + */ static char * ngx_http_upstream_check_init_main_conf(ngx_conf_t *cf, void *conf) { @@ -3755,6 +3917,10 @@ ngx_http_upstream_check_create_loc_conf(ngx_conf_t *cf) } +/** + *Nginx配置系统中用于初始化服务器(server)配置的函数, + *特别用于处理用HTTP协议检查的服务器检查相关的配置项 + */ static char * ngx_http_upstream_check_init_srv_conf(ngx_conf_t *cf, void *conf) { @@ -3836,7 +4002,11 @@ ngx_http_upstream_check_init_srv_conf(ngx_conf_t *cf, void *conf) return NGX_CONF_OK; } -/*合并location configuration*/ + +/** + *Nginx配置系统中用于合并特定配置段的函数 + *用于合并location configuration + */ static char * ngx_http_upstream_check_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) @@ -3852,6 +4022,10 @@ ngx_http_upstream_check_merge_loc_conf(ngx_conf_t *cf, void *parent, } +/** + *在Nginx配置中初始化对服务器检查的共享内存区域。 + *它根据配置中的对等体数量和共享内存大小设置,生成共享内存名称,分配共享内存,并设置初始化函数。 + */ static char * ngx_http_upstream_check_init_shm(ngx_conf_t *cf, void *conf) { @@ -3895,6 +4069,7 @@ ngx_http_upstream_check_init_shm(ngx_conf_t *cf, void *conf) } +/*根据给定的代数生成一个共享内存区域的名称。这个名称是唯一的,可以用于标识和访问特定的共享内存区域。*/ static ngx_int_t ngx_http_upstream_check_get_shm_name(ngx_str_t *shm_name, ngx_pool_t *pool, ngx_uint_t generation) @@ -3915,6 +4090,10 @@ ngx_http_upstream_check_get_shm_name(ngx_str_t *shm_name, ngx_pool_t *pool, } +/** + *为Nginx的服务器健康检查模块初始化共享内存区域 + *处理了从旧的共享内存数据继承状态的情况,以及在没有旧数据时分配和初始化新的共享内存数据。 + */ static ngx_int_t ngx_http_upstream_check_init_shm_zone(ngx_shm_zone_t *shm_zone, void *data) { @@ -4069,6 +4248,11 @@ failure: } +/** + *在Nginx的当前周期结构中查找具有特定名称和标签的共享内存区域。 + *它通过遍历共享内存列表,比较名称和标签来确定匹配项。 + *如果找到匹配的共享内存区域,它将返回该区域的指针;如果没有找到,它将返回 NULL。 + */ static ngx_shm_zone_t * ngx_shared_memory_find(ngx_cycle_t *cycle, ngx_str_t *name, void *tag) { @@ -4110,6 +4294,10 @@ ngx_shared_memory_find(ngx_cycle_t *cycle, ngx_str_t *name, void *tag) } +/** + *在Nginx的共享内存中搜索与给定地址匹配的对等体。它通过比较套接字长度和地址来确定匹配项。 + *如果找到匹配的对等体,它将返回该对等体的指针;如果没有找到,它将返回 NULL。 + */ static ngx_http_upstream_check_peer_shm_t * ngx_http_upstream_check_find_shm_peer(ngx_http_upstream_check_peers_shm_t *p, ngx_addr_t *addr) @@ -4134,6 +4322,9 @@ ngx_http_upstream_check_find_shm_peer(ngx_http_upstream_check_peers_shm_t *p, } +/** + *初始化一个用于跟踪和同步服务器健康状况的结构,能够确保检查是线程安全的。 + */ static ngx_int_t ngx_http_upstream_check_init_shm_peer(ngx_http_upstream_check_peer_shm_t *psh, ngx_http_upstream_check_peer_shm_t *opsh, ngx_uint_t init_down, @@ -4189,6 +4380,10 @@ ngx_http_upstream_check_init_shm_peer(ngx_http_upstream_check_peer_shm_t *psh, } +/** + *用于初始化对服务器的健康检查功能 + *是高可用性配置的一部分,用来确保后端服务的健康和性能 + */ static ngx_int_t ngx_http_upstream_check_init_process(ngx_cycle_t *cycle) { @@ -4205,4 +4400,3 @@ ngx_http_upstream_check_init_process(ngx_cycle_t *cycle) return ngx_http_upstream_check_add_timers(cycle); } -