zabbix原始碼閱讀--zabbix_agent
zabbix是一個實時監控系統,可以監控伺服器的執行狀態(cpu,記憶體,埠),並且可以傳送報警郵件和簡訊,或者執行遠端命令.由於工作上需要對zabbix進行二次開發,所以藉此機會閱讀了一下zabbix的原始碼.zabbix前臺是php實現的,後臺是用c寫的,按功能分為幾個部分:agent,server,proxy,sender. zabbix_agent負責收集機器上的資料(比如cpu利用率,記憶體剩餘量等)傳送給zabbix_server,zabbix_server負責收集zabbix_agent或者zabbix_proxy傳送過來的資料,更新資料庫,而前臺的php程式碼就可以從資料庫內拿出這些資料進行顯示。
先看zabbix_agent,它預設會啟動三個程式:collector_thread、listener_thread、active_checks_thread
/* start the collector thread */
thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t));
thread_args->thread_num = thread_num;
thread_args->args = NULL;
threads[thread_num++] = zbx_thread_start(collector_thread, thread_args);
/* start listeners */
for (i = 0; i < CONFIG_ZABBIX_FORKS; i++)
{
thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t));
thread_args->thread_num = thread_num;
thread_args->args = &listen_sock;
threads[thread_num++] = zbx_thread_start(listener_thread, thread_args);
}
/* start active check */
if (0 == CONFIG_DISABLE_ACTIVE)
{
activechk_args.host = CONFIG_HOSTS_ALLOWED;
activechk_args.port = (unsigned short)CONFIG_SERVER_PORT;
thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t));
thread_args->thread_num = thread_num;
thread_args->args = &activechk_args;
threads[thread_num++] = zbx_thread_start(active_checks_thread, thread_args);
}
其中collector_thread會每隔1s收集本機的cpu狀態存入結構體ZBX_CPUS_STAT_DATA中,將磁碟的狀態存入結構體ZBX_DISKDEVICES_DATA
typedef struct
{
zbx_uint64_t h_counter[ZBX_CPU_STATE_COUNT][MAX_COLLECTOR_HISTORY];
unsigned char h_status[MAX_COLLECTOR_HISTORY];
int h_first;
int h_count;
int cpu_num;
}
ZBX_SINGLE_CPU_STAT_DATA;
typedef struct
{
ZBX_SINGLE_CPU_STAT_DATA *cpu;
int count;
}
ZBX_CPUS_STAT_DATA;
typedef struct c_single_diskdevice_data
{
char name[32];
int index;
time_t clock[MAX_COLLECTOR_HISTORY];
zbx_uint64_t r_sect[MAX_COLLECTOR_HISTORY];
zbx_uint64_t r_oper[MAX_COLLECTOR_HISTORY];
zbx_uint64_t r_byte[MAX_COLLECTOR_HISTORY];
zbx_uint64_t w_sect[MAX_COLLECTOR_HISTORY];
zbx_uint64_t w_oper[MAX_COLLECTOR_HISTORY];
zbx_uint64_t w_byte[MAX_COLLECTOR_HISTORY];
double r_sps[ZBX_AVG_COUNT];
double r_ops[ZBX_AVG_COUNT];
double r_bps[ZBX_AVG_COUNT];
double w_sps[ZBX_AVG_COUNT];
double w_ops[ZBX_AVG_COUNT];
double w_bps[ZBX_AVG_COUNT];
} ZBX_SINGLE_DISKDEVICE_DATA;
typedef struct c_diskdevices_data
{
int count;
ZBX_SINGLE_DISKDEVICE_DATA device[MAX_DISKDEVICES];
} ZBX_DISKDEVICES_DATA;
zabbix_agent和zabbix_server通訊有兩種方式:主動和被動,即它可以主動的傳送資訊給zabbix_server,也可以等zabbix_server請求時在傳送相關的資訊進行響應。預設情況這兩個方式都開啟了。另外,zabbix_server和zabbix_agent通訊的協議是json格式的,詳細格式請查閱官網文件。
listener_thread程式是負責被動方式,它負責監聽10050埠,然後等待server端的請求並進行響應,請看下面的程式碼(listener.c)
static void process_listener(zbx_sock_t *s)
{
AGENT_RESULT result;
char *command;
char **value = NULL;
int ret;
if (SUCCEED == (ret = zbx_tcp_recv_to(s, &command, CONFIG_TIMEOUT)))
{
zbx_rtrim(command, "\r\n");
zabbix_log(LOG_LEVEL_DEBUG, "Requested [%s]", command);
init_result(&result);
process(command, 0, &result);
if (NULL == (value = GET_TEXT_RESULT(&result)))
value = GET_MSG_RESULT(&result);
if (NULL != value)
{
zabbix_log(LOG_LEVEL_DEBUG, "Sending back [%s]", *value);
ret = zbx_tcp_send_to(s, *value, CONFIG_TIMEOUT);
}
free_result(&result);
}
if (FAIL == ret)
zabbix_log(LOG_LEVEL_DEBUG, "Process listener error: %s", zbx_tcp_strerror());
}
值得一提的是從伺服器接收的變數command,它其實就是我們在前臺頁面新增item時填的key,接下來有這麼一個結構
ZBX_METRIC parameters_common[] =
/* KEY FLAG FUNCTION ADD_PARAM TEST_PARAM */
{
{"agent.ping", 0, AGENT_PING, 0, 0},
{"agent.version", 0, AGENT_VERSION, 0, 0},
{"system.localtime", 0, SYSTEM_LOCALTIME, 0, 0},
{"system.run", CF_USEUPARAM, SYSTEM_RUN, 0, "echo test"},
{"web.page.get", CF_USEUPARAM, WEB_PAGE_GET, 0, "localhost,,80"},
{"web.page.perf", CF_USEUPARAM, WEB_PAGE_PERF, 0, "localhost,,80"},
{"web.page.regexp", CF_USEUPARAM, WEB_PAGE_REGEXP, 0, "localhost,,80,OK"},
}
這個結構體將key和agent接收到key後執行的function聯絡到了一起
active_checks_thread程式是負責主動傳送收集到的資訊給zabbix_server的。除此之外,他還負責傳送心跳包已經更新自己維護的一個active_checks條目表,部分程式碼(active.c:ZBX_THREAD_ENTRY(active_checks_thread, args))如下:
while (ZBX_IS_RUNNING())
{
if (time(NULL) >= nextsend)
{
send_buffer(activechk_args.host, activechk_args.port); //負責傳送心跳包
nextsend = (int)time(NULL) + 1;
}
if (time(NULL) >= nextrefresh)
{
zbx_setproctitle("poller [getting list of active checks]");
if (FAIL == refresh_active_checks(activechk_args.host, activechk_args.port)) //更新自己維護的一個active_checks條目表
{
nextrefresh = (int)time(NULL) + 60;
}
else
{
nextrefresh = (int)time(NULL) + CONFIG_REFRESH_ACTIVE_CHECKS;
}
}
if (time(NULL) >= nextcheck && CONFIG_BUFFER_SIZE / 2 > buffer.pcount)
{
zbx_setproctitle("poller [processing active checks]");
process_active_checks(activechk_args.host, activechk_args.port); //主動傳送收集到的資訊給zabbix_server
if (CONFIG_BUFFER_SIZE / 2 <= buffer.pcount) /* failed to complete processing active checks */
continue;
nextcheck = get_min_nextcheck();
if (FAIL == nextcheck)
nextcheck = (int)time(NULL) + 60;
}
else
{
zabbix_log(LOG_LEVEL_DEBUG, "Sleeping for %d second(s)", 1);
zbx_setproctitle("poller [sleeping for %d second(s)]", 1);
zbx_sleep(1);
}
}
轉載請註明出處:http://blog.csdn.net/liujian0616/article/details/7932323
相關文章
- 【Zabbix】zabbix_agent安裝指令碼指令碼
- 【原始碼閱讀】AndPermission原始碼閱讀原始碼
- 【原始碼閱讀】Glide原始碼閱讀之with方法(一)原始碼IDE
- 【原始碼閱讀】Glide原始碼閱讀之into方法(三)原始碼IDE
- ReactorKit原始碼閱讀React原始碼
- AQS原始碼閱讀AQS原始碼
- CountDownLatch原始碼閱讀CountDownLatch原始碼
- HashMap 原始碼閱讀HashMap原始碼
- delta原始碼閱讀原始碼
- 原始碼閱讀-HashMap原始碼HashMap
- NGINX原始碼閱讀Nginx原始碼
- Mux 原始碼閱讀UX原始碼
- HashMap原始碼閱讀HashMap原始碼
- fuzz原始碼閱讀原始碼
- RunLoop 原始碼閱讀OOP原始碼
- express 原始碼閱讀Express原始碼
- muduo原始碼閱讀原始碼
- stack原始碼閱讀原始碼
- 【原始碼閱讀】Glide原始碼閱讀之load方法(二)原始碼IDE
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- JDK原始碼閱讀:Object類閱讀筆記JDK原始碼Object筆記
- Laravel 原始碼閱讀 - QueueLaravel原始碼
- Vollery原始碼閱讀(—)原始碼
- 使用OpenGrok閱讀原始碼原始碼
- 如何閱讀Java原始碼?Java原始碼
- buffer 原始碼包閱讀原始碼
- 原始碼閱讀技巧篇原始碼
- 如何閱讀框架原始碼框架原始碼
- 再談原始碼閱讀原始碼
- Laravel 原始碼閱讀 - EloquentLaravel原始碼
- 如何閱讀jdk原始碼?JDK原始碼
- express 原始碼閱讀(全)Express原始碼
- Vuex原始碼閱讀分析Vue原始碼
- React原始碼閱讀:setStateReact原始碼
- ArrayList原始碼閱讀(增)原始碼
- ThreadLocal原始碼閱讀thread原始碼
- snabbdom 原始碼閱讀分析原始碼
- koa原始碼閱讀[0]原始碼