ngx_int_t ngx_tcp_upstream_init_main_check_conf(ngx_conf_t *cf, void*conf) { ngx_tcp_upstream_main_conf_t *umcf = conf; ngx_uint_t i, shm_size, need_check; ngx_str_t *shm_name; ngx_shm_zone_t *shm_zone; ngx_tcp_upstream_srv_conf_t **uscfp; uscfp = umcf->upstreams.elts; need_check = 0; for (i = 0; i < umcf->upstreams.nelts; i++) { if (uscfp[i]->check_interval) { ngx_tcp_upstream_init_check_conf(uscfp[i]); need_check = 1; } } if (need_check) { ngx_tcp_check_shm_generation++; shm_name = &umcf->peers_conf->check_shm_name; if (ngx_tcp_check_get_shm_name(shm_name, cf->pool) == NGX_ERROR) { return NGX_ERROR; } /*the default check shmare memory size*/ shm_size = (umcf->upstreams.nelts + 1 )* ngx_pagesize; shm_size = shm_size < umcf->check_shm_size ? umcf->check_shm_size : shm_size; shm_zone = ngx_shared_memory_add(cf, shm_name, shm_size, &ngx_tcp_upstream_module); ngx_log_debug2(NGX_LOG_DEBUG_TCP, cf->log, 0, "[tcp_upstream] upsteam:%V, shm_zone size:%ui", shm_name, shm_size); shm_zone->data = umcf->peers_conf; check_peers_ctx = umcf->peers_conf; shm_zone->init = ngx_tcp_upstream_check_init_shm_zone; } else { check_peers_ctx = NULL; } return NGX_OK; }
static ngx_int_t ngx_tcp_upstream_check_status_handler(ngx_http_request_t *r) { ngx_buf_t *b; ngx_str_t shm_name; ngx_int_t rc; ngx_uint_t i; ngx_chain_t out; ngx_shm_zone_t *shm_zone; ngx_tcp_check_peer_shm_t *peer_shm; ngx_tcp_check_peers_shm_t *peers_shm; ngx_tcp_check_peer_conf_t *peer_conf; ngx_tcp_check_peers_conf_t *peers_conf; if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } r->headers_out.content_type.len = sizeof("text/html; charset=utf-8") - 1; r->headers_out.content_type.data = (u_char *) "text/html; charset=utf-8"; if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } if (ngx_tcp_check_get_shm_name(&shm_name, r->pool) == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } shm_zone = ngx_shared_memory_find((ngx_cycle_t *)ngx_cycle, &shm_name, &ngx_tcp_upstream_module); if (shm_zone == NULL || shm_zone->data == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[tcp upstream check] can not find the shared memory zone \"%V\" ", &shm_name); return NGX_HTTP_INTERNAL_SERVER_ERROR; } peers_conf = shm_zone->data; peers_shm = peers_conf->peers_shm; peer_conf = peers_conf->peers.elts; peer_shm = peers_shm->peers; b = ngx_create_temp_buf(r->pool, ngx_pagesize); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } out.buf = b; out.next = NULL; b->last = ngx_sprintf(b->last, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\n" "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" "<head>\n" " <title>Nginx tcp upstream check status</title>\n" "</head>\n" "<body>\n" "<h1>Nginx tcp upstream check status</h1>\n" "<h2>Check upstream server number: %ui, shm_name: %V</h2>\n" "<table style=\"background-color:white\" cellspacing=\"0\" cellpadding=\"3\" border=\"1\">\n" " <tr bgcolor=\"#C0C0C0\">\n" " <th>Index</th>\n" " <th>Name</th>\n" " <th>Status</th>\n" " <th>Business</th>\n" " <th>Rise counts</th>\n" " <th>Fall counts</th>\n" " <th>Access counts</th>\n" " <th>Check type</th>\n" " </tr>\n", peers_conf->peers.nelts, &shm_name); for (i = 0; i < peers_conf->peers.nelts; i++) { b->last = ngx_sprintf(b->last, " <tr%s>\n" " <td>%ui</td>\n" " <td>%V</td>\n" " <td>%s</td>\n" " <td>%ui</td>\n" " <td>%ui</td>\n" " <td>%ui</td>\n" " <td>%ui</td>\n" " <td>%s</td>\n" " </tr>\n", peer_shm[i].down ? " bgcolor=\"#FF0000\"" : "", i, &peer_conf[i].peer->name, peer_shm[i].down ? "down" : "up", peer_shm[i].business, peer_shm[i].rise_count, peer_shm[i].fall_count, peer_shm[i].access_count, peer_conf[i].conf->check_type_conf->name); } b->last = ngx_sprintf(b->last, "</table>\n" "</body>\n" "</html>\n"); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_tcp_check_init_process(ngx_cycle_t *cycle) { ngx_str_t shm_name; ngx_uint_t i; ngx_msec_t t, delay; check_conf_t *cf; ngx_shm_zone_t *shm_zone; ngx_tcp_check_peer_shm_t *peer_shm; ngx_tcp_check_peers_shm_t *peers_shm; ngx_tcp_check_peer_conf_t *peer_conf; ngx_tcp_check_peers_conf_t *peers_conf; ngx_tcp_upstream_srv_conf_t *uscf; if (ngx_tcp_check_get_shm_name(&shm_name, cycle->pool) == NGX_ERROR) { return NGX_ERROR; } shm_zone = ngx_shared_memory_find(cycle, &shm_name, &ngx_tcp_upstream_module); if (shm_zone == NULL || shm_zone->data == NULL) { return NGX_OK; } peers_conf = shm_zone->data; peers_shm = peers_conf->peers_shm; ngx_log_debug2(NGX_LOG_DEBUG_TCP, cycle->log, 0, "tcp check upstream init_process, shm_name: %V, peer number: %ud", &shm_name, peers_conf->peers.nelts); srand(ngx_pid); peer_conf = peers_conf->peers.elts; peer_shm = peers_shm->peers; for (i = 0; i < peers_conf->peers.nelts; i++) { peer_conf[i].shm = &peer_shm[i]; peer_conf[i].check_ev.handler = ngx_tcp_check_begin_handler; peer_conf[i].check_ev.log = cycle->log; peer_conf[i].check_ev.data = &peer_conf[i]; peer_conf[i].check_ev.timer_set = 0; peer_conf[i].check_timeout_ev.handler = ngx_tcp_check_timeout_handler; peer_conf[i].check_timeout_ev.log = cycle->log; peer_conf[i].check_timeout_ev.data = &peer_conf[i]; peer_conf[i].check_timeout_ev.timer_set = 0; uscf = peer_conf[i].conf; cf = uscf->check_type_conf; if (cf->need_pool) { peer_conf[i].pool = ngx_create_pool(ngx_pagesize, cycle->log); if (peer_conf[i].pool == NULL) { return NGX_ERROR; } } peer_conf[i].send_handler = cf->send_handler; peer_conf[i].recv_handler = cf->recv_handler; peer_conf[i].init = cf->init; peer_conf[i].parse = cf->parse; peer_conf[i].reinit = cf->reinit; /* Default delay interval is 1 second. I don't want to trigger the check event too close. */ delay = uscf->check_interval > 1000 ? uscf->check_interval : 1000; t = ngx_random() % delay; ngx_add_timer(&peer_conf[i].check_ev, t); } return NGX_OK; }