-
Sy
chevron_right
Настройки таймаута и количества попыток для запросов SNMP в Zabbix 3.4
pubsub.slavino.sk / sysadmblog · Sunday, 27 September, 2020 - 08:00 edit · 4 minutes
Ранее, чтобы уменьшить количество вызовов скриптов внешнего опроса, в конфигурации моих сереров Zabbix было выставлено максимально возможное значение таймаута - 30 секунд, а каждый такой скрипт запрашивал как можно больше значений у устройства и отправлял полученные значения в Zabbix при помощи утилиты zabbix_sender. Если скрипт успевал снять все необходимые данные, укладываясь в отведённые для его работы 30 секунд, то всё хорошо. Если скрипт не укладывался в 30 секунд, то процедуру опроса делили на несколько частей, так чтобы каждая из них уложилась в 30 секунд. Затем в Zabbix'е заводили по отдельному элементу данных для вызова скрипта, указывая ему какую именно часть данных нужно снять с устройства.
При переходе с Zabbix 2.0 на 2.2 изменение настроек таймаута SNMP привело к большим проблемам: использование процессов Poller выросло до 100% и сервер перестал успевать опрашивать оборудование в необходимом темпе. Происходило это потому, что первый же запрос SNMP к недоступному устройству растягивался до 30 секунд, в течение которых процесс просто ждал ответа от устройства, не занимаясь больше ничем.
Если вы не используете скриптов внешнего опроса или значение таймаута в конфигурации Zabbix имеет маленькое значение, или на вашем сервере Zabbix много оперативной памяти, то для вас это изменение не будет представлять никаких особых проблем - можно просто увеличить количество процессов Poller. Мне же в моём случае было просто жалко тратить оперативную память на процессы, которые фактически ничем не занимались. Прежний Zabbix без проблем справлялся с опросом, используя значительно меньше оперативной памяти, значит и новый тоже может. Я тогда выполнил откат до прежней версии Zabbix и стал изучать исходные тексты Zabbix с целью вернуть прежние значения таймаута в запросы SNMP.
Получившиеся исправления ранее уже были описаны в рамках более крупной статьи Установка и настройка Zabbix 2.2.0 в Debian Wheezy , но там им не уделялось достаточного внимания. На этот раз я опишу заплатку более подробно.
Задеклалируем изменения, которые собираемся внести, отредактировав пример файла конфигурации conf/zabbix_server.conf:
Index: zabbix-3.4.12-1+buster/conf/zabbix_server.confОбъявим переменные CONFIG_SNMP_TIMEOUT и CONFIG_SNMP_RETRIES в том же файле, где объявлена переменная CONFIG_TIMEOUT. Это файл src/libs/zbxconf/cfg.c:
===================================================================
--- zabbix-3.4.12-1+buster.orig/conf/zabbix_server.conf
+++ zabbix-3.4.12-1+buster/conf/zabbix_server.conf
@@ -439,6 +439,26 @@ DBUser=zabbix
Timeout=4
+### Option: SNMPTimeout
+# Specifies how long we wait for SNMP device (in seconds).
+#
+# Mandatory: no
+# Range: 1-30
+# Default:
+# SNMPTimeout=1
+
+SNMPTimeout=1
+
+### Option: SNMPRetries
+# Specifies how many times to trying request for SNMP device
+#
+# Mandatory: no
+# Range: 1-10
+# Default:
+# SNMPRetries=3
+
+SNMPRetries=3
+
### Option: TrapperTimeout
# Specifies how many seconds trapper may spend processing new data.
#
Index: zabbix-3.4.12-1+buster/src/libs/zbxconf/cfg.cПропишем эти же объявления в заголовочный файл include/cfg.h, на этот раз - как внешние объявления:
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxconf/cfg.c
+++ zabbix-3.4.12-1+buster/src/libs/zbxconf/cfg.c
@@ -31,6 +31,8 @@ char *CONFIG_LOG_FILE = NULL;
int CONFIG_LOG_FILE_SIZE = 1;
int CONFIG_ALLOW_ROOT = 0;
int CONFIG_TIMEOUT = 3;
+int CONFIG_SNMP_TIMEOUT = 1;
+int CONFIG_SNMP_RETRIES = 3;
static int __parse_cfg_file(const char *cfg_file, struct cfg_line *cfg, int level, int optional, int strict);
Index: zabbix-3.4.12-1+buster/include/cfg.hТеперь нужно научить сервер Zabbix и Zabbix-прокси извлекать значения из файлов конфигурации в эти переменные. Отредактируем файлы src/zabbix_server/server.c и src/zabbix_proxy/proxy.c следующим образом:
===================================================================
--- zabbix-3.4.12-1+buster.orig/include/cfg.h
+++ zabbix-3.4.12-1+buster/include/cfg.h
@@ -46,6 +46,8 @@ extern char *CONFIG_LOG_FILE;
extern int CONFIG_LOG_FILE_SIZE;
extern int CONFIG_ALLOW_ROOT;
extern int CONFIG_TIMEOUT;
+extern int CONFIG_SNMP_TIMEOUT;
+extern int CONFIG_SNMP_RETRIES;
struct cfg_line
{
Index: zabbix-3.4.12-1+buster/src/zabbix_server/server.cРеализация функций опроса по SNMP находится в файле src/zabbix_server/poller/checks_snmp.c, но прежде чем редактировать его, заменим в заголовочном файле src/zabbix_server/poller/checks_snmp.h объявление внешней переменной CONFIG_TIMEOUT на объявления внешних переменных CONFIG_SNMP_TIMEOUT и CONFIG_SNMP_RETRIES:
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_server/server.c
+++ zabbix-3.4.12-1+buster/src/zabbix_server/server.c
@@ -602,6 +602,10 @@ static void zbx_load_config(ZBX_TASK_EX
PARM_OPT, 0, 0},
{"Timeout", &CONFIG_TIMEOUT, TYPE_INT,
PARM_OPT, 1, 30},
+ {"SNMPTimeout", &CONFIG_SNMP_TIMEOUT, TYPE_INT,
+ PARM_OPT, 1, 30},
+ {"SNMPRetries", &CONFIG_SNMP_RETRIES, TYPE_INT,
+ PARM_OPT, 1, 10},
{"TrapperTimeout", &CONFIG_TRAPPER_TIMEOUT, TYPE_INT,
PARM_OPT, 1, 300},
{"UnreachablePeriod", &CONFIG_UNREACHABLE_PERIOD, TYPE_INT,
Index: zabbix-3.4.12-1+buster/src/zabbix_proxy/proxy.c
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_proxy/proxy.c
+++ zabbix-3.4.12-1+buster/src/zabbix_proxy/proxy.c
@@ -623,6 +623,10 @@ static void zbx_load_config(ZBX_TASK_EX
PARM_OPT, 0, 0},
{"Timeout", &CONFIG_TIMEOUT, TYPE_INT,
PARM_OPT, 1, 30},
+ {"SNMPTimeout", &CONFIG_SNMP_TIMEOUT, TYPE_INT,
+ PARM_OPT, 1, 30},
+ {"SNMPRetries", &CONFIG_SNMP_RETRIES, TYPE_INT,
+ PARM_OPT, 1, 10},
{"TrapperTimeout", &CONFIG_TRAPPER_TIMEOUT, TYPE_INT,
PARM_OPT, 1, 300},
{"UnreachablePeriod", &CONFIG_UNREACHABLE_PERIOD, TYPE_INT,
Index: zabbix-3.4.12-1+buster/src/zabbix_server/poller/checks_snmp.hА теперь можно отредактировать сам файл src/zabbix_server/poller/checks_snmp.c:
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_server/poller/checks_snmp.h
+++ zabbix-3.4.12-1+buster/src/zabbix_server/poller/checks_snmp.h
@@ -26,7 +26,8 @@
#include "sysinfo.h"
extern char *CONFIG_SOURCE_IP;
-extern int CONFIG_TIMEOUT;
+extern int CONFIG_SNMP_TIMEOUT;
+extern int CONFIG_SNMP_RETRIES;
#ifdef HAVE_NETSNMP
void zbx_init_snmp(void);
Index: zabbix-3.4.12-1+buster/src/zabbix_server/poller/checks_snmp.cПри помощи команды «grep -R CONFIG_TIMEOUT | grep -i snmp» в исходных текстах можно найти ещё один любопытный фрагмент в файле libs/zbxdbcache/dbconfig.c, где можно увидеть отключение повторных попыток опроса по SNMP всего узла, если он не отвечает по SNMP:
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_server/poller/checks_snmp.c
+++ zabbix-3.4.12-1+buster/src/zabbix_server/poller/checks_snmp.c
@@ -456,8 +456,10 @@ static struct snmp_session *zbx_snmp_ope
break;
}
- session.timeout = CONFIG_TIMEOUT * 1000 * 1000; /* timeout of one attempt in microseconds */
- /* (net-snmp default = 1 second) */
+ session.timeout = CONFIG_SNMP_TIMEOUT * 1000 * 1000; /* timeout of one attempt in microseconds */
+ /* (net-snmp default = 1 second) */
+ session.retries = CONFIG_SNMP_RETRIES - 1; /* number of retries after failed attempt */
+ /* (net-snmp default = 5) */
#ifdef HAVE_IPV6
if (SUCCEED != get_address_family(item->interface.addr, &family, error, max_error_len))
@@ -1095,7 +1097,7 @@ static int zbx_snmp_walk(struct snmp_ses
pdu->max_repetitions = max_vars;
}
- ss->retries = (0 == bulk || (1 == max_vars && == level) ? 1 : 0);
+ ss->retries = (0 == bulk || (1 == max_vars && 0 == level) ? 1 : 0) * (CONFIG_SNMP_RETRIES - 1);
/* communicate with agent */
status = snmp_synch_response(ss, pdu, &response);
@@ -1304,7 +1306,7 @@ static int zbx_snmp_get_values(struct sn
goto out;
}
- ss->retries = (1 == mapping_num && 0 == level ? 1 : 0);
+ ss->retries = (1 == mapping_num && 0 == level ? 1 : 0) * (CONFIG_SNMP_RETRIES - 1);
retry:
status = snmp_synch_response(ss, pdu, &response);
static void DCincrease_disable_until(const ZBX_DC_ITEM *item, ZBX_DC_HOST *host, int now)Вопрос, стоит ли исправлять значение таймаута для проверок SNMP в этой функции, я оставлю на размышление. Если значение CONFIG_SNMP_TIMEOUT меньше CONFIG_TIMEOUT, то опрос по SNMP после временных перебоев будет приостанавливаться на меньшее время и, соответственно, восстанавливаться быстрее. Нагрузка на процессы Poller при этом может слегка повыситься, т.к. доступность узлов SNMP будет проверяться чаще. Если вы всё же решитесь поменять значение таймаута в этой функции, то вот очевидный патч для файла libs/zbxdbcache/dbconfig.c:
{
switch (item->type)
{
case ITEM_TYPE_ZABBIX:
if (0 != host->errors_from)
host->disable_until = now + CONFIG_TIMEOUT;
break;
case ITEM_TYPE_SNMPv1:
case ITEM_TYPE_SNMPv2c:
case ITEM_TYPE_SNMPv3:
if (0 != host->snmp_errors_from)
host->snmp_disable_until = now + CONFIG_TIMEOUT;
break;
case ITEM_TYPE_IPMI:
if (0 != host->ipmi_errors_from)
host->ipmi_disable_until = now + CONFIG_TIMEOUT;
break;
case ITEM_TYPE_JMX:
if (0 != host->jmx_errors_from)
host->jmx_disable_until = now + CONFIG_TIMEOUT;
break;
default:
/* nothing to do */;
}
}
Index: zabbix-3.4.12-1+buster/src/libs/zbxdbcache/dbconfig.cПолную версию описанной здесь заплатки можно взять по ссылке zabbix3_4_12_snmp_timeout_retries.patch .
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxdbcache/dbconfig.c
+++ zabbix-3.4.12-1+buster/src/libs/zbxdbcache/dbconfig.c
@@ -448,7 +448,7 @@ static void DCincrease_disable_until(con
case ITEM_TYPE_SNMPv2c:
case ITEM_TYPE_SNMPv3:
if (0 != host->snmp_errors_from)
- host->snmp_disable_until = now + CONFIG_TIMEOUT;
+ host->snmp_disable_until = now + CONFIG_SNMP_TIMEOUT;
break;
case ITEM_TYPE_IPMI:
if (0 != host->ipmi_errors_from)