深入理解 Ganglia 之 gmond

0. 引言

gmond 是 ganglia 中最核心的组成部分,负责指标的采集、发送、收集等,这篇文章就来看看 gmond 的重要特性。

1. 指标采集

gmond 有两种重要功能:采集指标和收集指标。所谓采集指标就是 gmond 运行具体的代码去计算指标的具体值,收集指标是说 gmond 接收来自其他 gmond 或者其他程序(比如 Hadoop 相关进程)的值。

每台需要采集指标的机器上都需要安装 gmond。gmond 本身可以采集的指标多达两百多个,具体可以通过命令 gmond -m 查看。除此之后 gmond 还可以收集 Hadoop 相关指标,只需要在 Hadoop 配置文件中配置一下 gmond 的 host 和 port。gmond 原生的指标都是通过每台机器上的 gmond 进程采集的,Hadoop 相关的指标是 Hadoop 相关进程(NameNode, DataNode, ResourceManager, NodeManager)发送给 gmond 的。

2. 自定义指标

除了 gmond 的原生指标,还支持用户自定义一些指标。自定指标有两种方式:

  1. 自定义 module ( C/C++/Python)
  2. gmetric

这两种方式各有各的好处。使用 module 的方式有点像侵入式。而使用 gmetric 的方式可以更快的添加一种指标。

2.1 gmetric

gmetric 的方式就是通过命令行工具,可以非常便捷的添加。

1
gmetric -n test_string -v 'hello value' -t string -d 10 -c /etc/ganglia/gmond.conf.bkeep -S '2.2.2.2:web'

关于参数可以参考 gmetric -h 输出。

2.2 module

使用 module 方式添加指标的方式可以自定义 C/C++/Python 的 module。gmond 启动的时候会根据 conf 文件加载需要使用的 module。对于 C/C++ 是 so 动态库,对于 Python 是 pyo 和 pyc 文件。如果我们需要自定义指标只需要提供 module 文件和 conf 即可。这里以 Python module 为例子说明一下。module 文件的框架如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# metric's handle
def handler(name):
# compute metric(metric name is name) value

def metric_init(parameter):
global descriptor

# init descriptor, binding the metric with corresponding handler
descriptors = [{'name': "metric_name",
'call_back': handler,
'value_type': 'float',
'format': '%f'}]
return descriptors

def metric_cleanup():
pass

module 文件中主要包括 metric_init() 函数,gmond 启动的时候载入 module,然后会调用 metric_init 函数得到 metric 和对应的 handler 函数。之后 metric 采集的时候直接调用相应的 handler 函数。除了 module 文件,还需要定义相应的 pyconf 文件。pyconf 文件中会定义需要采集的 metric name 和对应的采集 module。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
modules {
module {
name = "custom_disk_metric" # module name,gmond 根据这个进行加载对应的 module
language = "python"
}
}

collection_group {
collect_every = 15
time_threshold = 45

metric {
name_match = "part_max_(.+)"
# metric name 可以使用正则。对应 module 中 metric_init 定义的指标会和这个地方比对,match 就会采集。
}
}

3. Deaf & Mute

在 gmond conf 文件中有两个配置项为 mute 和 deaf。

1. mute

一旦 gmond 的 mute 参数被设置为 true,则它自身不进行指标收集且不发送。但是会收集来自其他节点的指标信息。

2. Deaf

deaf node 其实很形象的,不接受其他 node 的指标数据。

4. data flow

在 gmond conf 中有几个选项如下

1
2
3
udp_send_channel
udp_recv_channel
tcp_accept_channel

其中 udp_send_channel 是 gmond 用来发送数据的,一般简单的配置如下。

1
2
3
4
5
6
udp_send_channel {
# bind_hostname = yes 用来控制数据源
host = host_name # 如果指定 host,则将 gmond 的采集数据发送这台 host 上。也就是单播模式
mcast_join = 239.2.17.45 # multicast 模式,不和 host 同时使用
port = 8649
}

gmond 给其他的 gmond 发送数据,接收源就需要指定 udp_recv_channel。可以定义多个接收端口。

1
2
3
udp_recv_channel {
port = 8649
}

tcp_accept_channel 用来开启一个 tcp server,通过指定的端口可以取到 gmond 采集的集群监控数据。一般 gmetad 就是通过这种方式来收集 gmond 的数据的。我们可以指定多个 tcp_accept_channel ,不同端口返回的数据其实来自同一份数据源,也就是 gmond 收集到的集群的最新状态信息的 xml 格式。如果我们也想获得 gmond 监控的集群数据,那么我们完全可以使用 8649 或者重新开一个端口,比如 8659。读取数据示例如下。

1
2
3
4
5
6
7
8
9
def read_gmond_data(host, port):
sock = create_socket(host, port)
xml_data = ''
buf = sock.recv(4096)
while len(buf):
xml_data += buf
buf = sock.recv(4096)
sock.close()
return xml_data

注意如果你要一直持续读取端口的数据,每次读取的时候都需要建立一次连接。

5. XDR

gmond 之间的数据交互使用 XDR (eXternal Data Representation) 协议,一种二进制传输协议。除此之外,外部应用也可以通过 XDR 协议将指标数据发送给 gmond,gmetric 实现自定义指标就是这种机制。关于 XDR 更详细的资料可以参考:eXternal Data Representation

6. 参考

  1. eXternal Data Representation