|
|
|
@ -1,8 +1,7 @@
|
|
|
|
|
|
|
|
|
|
#include <nginx.h>
|
|
|
|
|
#include "ngx_http_upstream_check_module.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <ngx_core.h>
|
|
|
|
|
#include <ngx_config.h>
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
@ -959,17 +978,19 @@ ngx_http_upstream_check_add_timers(ngx_cycle_t *cycle)
|
|
|
|
|
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,8 +1205,9 @@ 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;
|
|
|
|
@ -1193,6 +1219,7 @@ 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);
|
|
|
|
|
|
|
|
|
@ -1201,12 +1228,57 @@ ngx_http_upstream_check_peek_handler(ngx_event_t *event)
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
@ -1422,6 +1506,14 @@ 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,6 +3249,15 @@ 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) {
|
|
|
|
|
|
|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|