我可以帮助您对此有所了解。但在此之前我必须告诉你,我不是 Java 程序员,而是 C/C++ 程序员。所以,这意味着我可以让你知道 ganglia 是如何工作的,你可以在 Java/Python 中找到等效的方法来重写你想要的代码。
请注意,ganglia 中没有 API 可以实现您想要的。
首先考虑以下神经节的设置以正确理解:

GS1 和 GS2 正在收集系统指标并将其推送给 GM。因此,根据您的问题,如果您想通过您自己的基于 Java/Python 的应用程序收集所有此类指标,那么您可能必须在主服务器上安装该应用程序(即用您自己的应用程序替换 GS)。
GS1 和 GS2 通过 UDP 单播通道或 UDP 多播通道发送所有收集的指标。建议在每个 gmond.conf 中启用 UDP 单播,以便于扩展。
我不会对 GS1 和 GS2 进行太多讨论,因为您的问题更多是关于用您自己的工具替换 GM。
GM 大量使用两个重要的库来建立 UDP 连接并将数据转换为自己的可读格式。它们是用于建立 UDP 连接并执行相关活动的APR (Apache Portable Runtime)和用于跨网络发送数据并执行 RPC 的XDR (外部数据表示)。
您需要首先在 Java 和 Python 中找到 APR 和 XDR 等效库。XDR 已经在 Java 中可用,并且 APR 可以替换为您自己的基本实现来执行网络间操作(即,创建 UDP 套接字等)。
打开ganglia 的gmond.c源文件,转到第 1436 行。你会发现一个 C 函数:
static void process_udp_recv_channel(const apr_pollfd_t *desc, apr_time_t now)
.
该函数主要执行“UDP 连接建立”和“数据转换为可读格式”活动。
上述函数的调用流程如下图所示:

现在,让我们扩展第 1436 行的函数以了解更多信息。
该函数的第一个参数携带IP、Port等网络参数,下面展开结构。您也可以在 Java 中找到类似的对象。
struct apr_pollfd_t {
apr_pool_t *p; /**< associated pool */
apr_datatype_e desc_type; /**< descriptor type */
apr_int16_t reqevents; /**< requested events */
apr_int16_t rtnevents; /**< returned events */
apr_descriptor desc; /**< @see apr_descriptor */
void *client_data; /**< allows app to associate context */
};
如果 SFLOW 被禁用,则第二个参数无关。
因此,从创建 APR 池、UDP 连接等开始。
socket = desc->desc.s;
channel = desc->client_data;
apr_pool_create(&p, global_context);
status = apr_socket_addr_get(&remotesa, APR_LOCAL, socket);
status = apr_sockaddr_info_get(&remotesa, NULL, remotesa->family, remotesa->port, 0, p);
/* Grab the data */
status = apr_socket_recvfrom(remotesa, socket, 0, buf, &len);
if(status != APR_SUCCESS)
{
apr_pool_destroy(p);
return;
}
apr_sockaddr_ip_buffer_get(remoteip, 256, remotesa);
/* Check the ACL */
if(Ganglia_acl_action( channel->acl, remotesa) != GANGLIA_ACCESS_ALLOW)
{
apr_pool_destroy(p);
return;
}
变量的所有声明都可以在展开的函数的开头找到(第 1439 到 1456 行)。
然后,创建 XDR 流:
xdrmem_create(&x, buf, max_udp_message_len, XDR_DECODE);
刷新保存元数据和指标值的结构的数据:
memset( &fmsg, 0, sizeof(Ganglia_metadata_msg));
memset( &vmsg, 0, sizeof(Ganglia_value_msg));
fmsg ( Ganglia_metadata_msg
) 和 vmsg ( Ganglia_value_msg
) 结构定义可以在gm_protocol.h头文件中找到。用 Java 重新编写它们。
然后,确定收到的消息是“元数据”还是“指标值”。
xdr_Ganglia_msg_formats(&x, &id); // this function is located in the source file gm_protocol_xdr.c and this file is generated by rpcgen.
注意:rpcgen是一个 rpc 编译器,它的解释可以在这个问题中找到。
注意:这是gm_protocol_xdr.c的链接。
这里,id
是一个enum
,它的声明如下所示:
enum Ganglia_msg_formats {
gmetadata_full = 128,
gmetric_ushort = 128 + 1,
gmetric_short = 128 + 2,
gmetric_int = 128 + 3,
gmetric_uint = 128 + 4,
gmetric_string = 128 + 5,
gmetric_float = 128 + 6,
gmetric_double = 128 + 7,
gmetadata_request = 128 + 8,
};
typedef enum Ganglia_msg_formats Ganglia_msg_formats;
根据 的值id
,您可以确定数据包具有什么样的值。为此,此函数调用另一个函数(实际上由 rpcgen 生成)来确定数据包具有的值类型,如果找到,它也将其转换为人类可读的格式。
功能是:
xdr_Ganglia_value_msg(&x, &vmsg);
您可以在gm_protocol_xdr.c第 275 行找到此函数的完整扩展。
之后,您可以对这些数据包做任何您想做的事情。
最后,您必须释放所有已分配的 XDR 变量和 APR 池。
我希望这能给你一个公平的想法来开始你自己的应用程序。