From b38d57249e247a2bcf5f285185cae237928f90f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Loyet?= Date: Thu, 11 Nov 2010 02:34:47 +0000 Subject: [PATCH] - add "listen queue len" stat (thx to Andrei Nigmatulin) --- sapi/fpm/config.m4 | 34 +++++++++++++++ sapi/fpm/fpm/fpm_conf.c | 2 +- sapi/fpm/fpm/fpm_config.h | 6 +++ sapi/fpm/fpm/fpm_process_ctl.c | 7 +++- sapi/fpm/fpm/fpm_sockets.c | 77 ++++++++++++++++++++++++++++++++++ sapi/fpm/fpm/fpm_sockets.h | 1 + sapi/fpm/fpm/fpm_status.c | 58 +++++++++++++++++++++---- sapi/fpm/fpm/fpm_status.h | 4 +- sapi/fpm/fpm/fpm_worker_pool.h | 1 + 9 files changed, 180 insertions(+), 10 deletions(-) diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 index 6a2105d1e61..fc5de678045 100644 --- a/sapi/fpm/config.m4 +++ b/sapi/fpm/config.m4 @@ -516,6 +516,39 @@ AC_DEFUN([AC_FPM_BUILTIN_ATOMIC], AC_MSG_RESULT([no]) ]) ]) + +AC_DEFUN([AC_FPM_LQ], +[ + have_lq=no + + AC_MSG_CHECKING([for TCP_INFO]) + + AC_TRY_COMPILE([ #include ], [struct tcp_info ti; int x = TCP_INFO;], [ + have_lq=tcp_info + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + if test "$have_lq" = "tcp_info"; then + AC_DEFINE([HAVE_LQ_TCP_INFO], 1, [do we have TCP_INFO?]) + fi + + if test "$have_lq" = "no" ; then + AC_MSG_CHECKING([for SO_LISTENQLEN]) + + AC_TRY_COMPILE([ #include ], [int x = SO_LISTENQLIMIT; int y = SO_LISTENQLEN;], [ + have_lq=so_listenq + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + if test "$have_lq" = "tcp_info"; then + AC_DEFINE([HAVE_LQ_SO_LISTENQ], 1, [do we have SO_LISTENQxxx?]) + fi + fi +]) dnl }}} AC_MSG_CHECKING(for FPM build) @@ -543,6 +576,7 @@ if test "$PHP_FPM" != "no"; then AC_FPM_CLOCK AC_FPM_TRACE AC_FPM_BUILTIN_ATOMIC + AC_FPM_LQ PHP_ARG_WITH(fpm-user,, [ --with-fpm-user[=USER] Set the user for php-fpm to run as. (default: nobody)], nobody, no) diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index 0b6dda4190b..e24d82fe189 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -576,7 +576,7 @@ static int fpm_conf_process_all_pools() /* {{{ */ return -1; } fpm_status_update_accepted_conn(wp->shm_status, 0); - fpm_status_update_activity(wp->shm_status, -1, -1, -1, 1); + fpm_status_update_activity(wp->shm_status, -1, -1, -1, 0, -1, 1); fpm_status_update_max_children_reached(wp->shm_status, 0); fpm_status_set_pm(wp->shm_status, wp->config->pm); /* memset(&fpm_status.last_update, 0, sizeof(fpm_status.last_update)); */ diff --git a/sapi/fpm/fpm/fpm_config.h b/sapi/fpm/fpm/fpm_config.h index 165bd7d62d1..50fb6e52cae 100644 --- a/sapi/fpm/fpm/fpm_config.h +++ b/sapi/fpm/fpm/fpm_config.h @@ -42,3 +42,9 @@ #define HAVE_FPM_TRACE 0 #endif +#if defined(HAVE_LQ_TCP_INFO) || defined(HAVE_LQ_SO_LISTENQ) +#define HAVE_FPM_LQ 1 +#else +#define HAVE_FPM_LQ 0 +#endif + diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c index 4eae0a2926f..2a4011ee803 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.c +++ b/sapi/fpm/fpm/fpm_process_ctl.c @@ -19,6 +19,7 @@ #include "fpm_request.h" #include "fpm_worker_pool.h" #include "fpm_status.h" +#include "fpm_sockets.h" #include "zlog.h" @@ -327,6 +328,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct int idle = 0; int active = 0; int children_to_fork; + unsigned cur_lq; if (wp->config == NULL) continue; @@ -352,7 +354,10 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct } /* update status structure for all PMs */ - fpm_status_update_activity(wp->shm_status, idle, active, idle + active, 0); + if (0 > fpm_socket_get_listening_queue(wp, &cur_lq, NULL)) { + cur_lq = 0; + } + fpm_status_update_activity(wp->shm_status, idle, active, idle + active, cur_lq, wp->listening_queue_len, 0); /* the rest is only used by PM_STYLE_DYNAMIC */ if (wp->config->pm != PM_STYLE_DYNAMIC) continue; diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c index 31f4c66a62a..80980bbdfb1 100644 --- a/sapi/fpm/fpm/fpm_sockets.c +++ b/sapi/fpm/fpm/fpm_sockets.c @@ -344,6 +344,10 @@ int fpm_sockets_init_main() /* {{{ */ break; } + if (0 > fpm_socket_get_listening_queue(wp, NULL, (unsigned *) &wp->listening_queue_len)) { + wp->listening_queue_len = -1; + } + if (wp->listening_socket == -1) { return -1; } @@ -373,3 +377,76 @@ int fpm_sockets_init_main() /* {{{ */ } /* }}} */ +#if HAVE_FPM_LQ + +#ifdef HAVE_LQ_TCP_INFO + +#include + +int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq) +{ + if (wp->listen_address_domain != FPM_AF_INET) { + return -1; + } + + struct tcp_info info; + socklen_t len = sizeof(info); + + if (0 > getsockopt(wp->listening_socket, IPPROTO_TCP, TCP_INFO, &info, &len)) { + return -1; + } + + /* kernel >= 2.6.24 return non-zero here, that means operation is supported */ + if (info.tcpi_sacked == 0) { + return -1; + } + + if (cur_lq) { + *cur_lq = info.tcpi_unacked; + } + + if (max_lq) { + *max_lq = info.tcpi_sacked; + } + + return 0; +} + +#endif + +#ifdef HAVE_LQ_SO_LISTENQ + +int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq) +{ + int val; + socklen_t len = sizeof(val); + + if (cur_lq) { + if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLEN, &val, &len)) { + return -1; + } + + *cur_lq = val; + } + + if (max_lq) { + if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) { + return -1; + } + + *max_lq = val; + } + + return 0; +} + +#endif + +#else + +int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq) +{ + return -1; +} + +#endif diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h index 8bd778ea507..b74fc234c2b 100644 --- a/sapi/fpm/fpm/fpm_sockets.h +++ b/sapi/fpm/fpm/fpm_sockets.h @@ -21,6 +21,7 @@ enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); int fpm_sockets_init_main(); +int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq); static inline int fd_set_blocked(int fd, int blocked) /* {{{ */ diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index 19285b193da..8353375194e 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -133,7 +133,7 @@ void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int } /* }}} */ -void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, int clear_last_update) /* {{{ */ +void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, unsigned cur_lq, int max_lq, int clear_last_update) /* {{{ */ { struct fpm_status_s status; @@ -146,6 +146,8 @@ void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int status.idle = idle; status.active = active; status.total = total; + status.cur_lq = cur_lq; + status.max_lq = max_lq; if (clear_last_update) { memset(&status.last_update, 0, sizeof(status.last_update)); } else { @@ -164,14 +166,28 @@ static void fpm_status_handle_status_txt(struct fpm_status_s *status, char **out } spprintf(output, 0, - "accepted conn: %lu\n" "pool: %s\n" "process manager: %s\n" + "accepted conn: %lu\n" +#if HAVE_FPM_LQ + "listen queue len: %u\n" + "max listen queue len: %d\n" +#endif "idle processes: %d\n" "active processes: %d\n" "total processes: %d\n" "max children reached: %u\n", - status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total, status->max_children_reached); + fpm_status_pool, + status->pm == PM_STYLE_STATIC ? "static" : "dynamic", + status->accepted_conn, +#if HAVE_FPM_LQ + status->cur_lq, + status->max_lq, +#endif + status->idle, + status->active, + status->total, + status->max_children_reached); spprintf(content_type, 0, "Content-Type: text/plain"); } @@ -185,15 +201,29 @@ static void fpm_status_handle_status_html(struct fpm_status_s *status, char **ou spprintf(output, 0, "\n" - "\n" "\n" "\n" + "\n" +#if HAVE_FPM_LQ + "\n" + "\n" +#endif "\n" "\n" "\n" "\n" "
accepted conn%lu
pool%s
process manager%s
accepted conn%lu
listen queue len%u
max listen queue len%d
idle processes%d
active processes%d
total processes%d
max children reached%u
", - status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total, status->max_children_reached); + fpm_status_pool, + status->pm == PM_STYLE_STATIC ? "static" : "dynamic", + status->accepted_conn, +#if HAVE_FPM_LQ + status->cur_lq, + status->max_lq, +#endif + status->idle, + status->active, + status->total, + status->max_children_reached); spprintf(content_type, 0, "Content-Type: text/html"); } @@ -207,15 +237,29 @@ static void fpm_status_handle_status_json(struct fpm_status_s *status, char **ou spprintf(output, 0, "{" - "\"accepted conn\":%lu," "\"pool\":\"%s\"," "\"process manager\":\"%s\"," + "\"accepted conn\":%lu," +#if HAVE_FPM_LQ + "\"listen queue len\":%u," + "\"max listen queue len\":%d," +#endif "\"idle processes\":%d," "\"active processes\":%d," "\"total processes\":%d," "\"max children reached\":%u" "}", - status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total, status->max_children_reached); + fpm_status_pool, + status->pm == PM_STYLE_STATIC ? "static" : "dynamic", + status->accepted_conn, +#if HAVE_FPM_LQ + status->cur_lq, + status->max_lq, +#endif + status->idle, + status->active, + status->total, + status->max_children_reached); spprintf(content_type, 0, "Content-Type: application/json"); } diff --git a/sapi/fpm/fpm/fpm_status.h b/sapi/fpm/fpm/fpm_status.h index e081f5eeb03..00e5af54e71 100644 --- a/sapi/fpm/fpm/fpm_status.h +++ b/sapi/fpm/fpm/fpm_status.h @@ -14,13 +14,15 @@ struct fpm_status_s { int idle; int active; int total; + unsigned cur_lq; + int max_lq; unsigned long int accepted_conn; unsigned int max_children_reached; struct timeval last_update; }; int fpm_status_init_child(struct fpm_worker_pool_s *wp); -void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, int clear_last_update); +void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, unsigned cur_lq, int max_lq, int clear_last_update); void fpm_status_update_accepted_conn(struct fpm_shm_s *shm, unsigned long int accepted_conn); void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm); void fpm_status_set_pm(struct fpm_shm_s *shm, int pm); diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h index 63aff9a55aa..7f240a20c28 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.h +++ b/sapi/fpm/fpm/fpm_worker_pool.h @@ -25,6 +25,7 @@ struct fpm_worker_pool_s { char *user, *home; /* for setting env USER and HOME */ enum fpm_address_domain listen_address_domain; int listening_socket; + int listening_queue_len; int set_uid, set_gid; /* config uid and gid */ int socket_uid, socket_gid, socket_mode;