如何从其他应用程序中读取神经节信息?

时间:2014-07-10 11:20:29

标签: java python ganglia

我已设法在我的群集上安装和配置Ganglia。我不想只看到ganglia web界面上的所有性能数据,而是想要从其他应用程序读取集群信息(应用程序可能是基于Java或Python的)。我无法找到是否可能。

是否有任何API可以读取Ganglia数据?

为了测试Ganglia,我使用了telnet master 8649,Ganglia在我的控制台上向我展示了漂亮的XML文本。但是我如何使用Java或Python做同样的事情呢?我绝对可以使用套接字连接到8649,但之后我需要向Ganglia守护进程发送一些内容吗?

1 个答案:

答案 0 :(得分:4)

我可以帮助您深入了解这一点。但在此之前我必须告诉你,我不是Java程序员,而是我是一名C / C ++程序员。所以,这意味着我可以让你知道,在神经节中如何工作,你可以在Java / Python中找到相应的方法来重写你想要的代码。

请注意,神经节中没有API可以实现您的目标。

首先考虑以下正确理解神经节的设置:

ganglia minimal setup

GS1和GS2正在收集系统指标并将其推向GM。 因此,根据您的问题,如果您希望通过自己的基于Java / Python的应用程序收集所有此类指标,则可能必须在主服务器上安装应用程序(即使用您自己的应用程序替换GS)。

GS1和GS2通过UDP单播信道或UDP多播信道发送所有收集的指标。建议在每个gmond.conf中启用UDP单播,以便于扩展。

我不会在GS1和GS2上讨论太多,因为你的问题更多的是用你自己的工具取代GM。

GM大量使用两个重要的库来建立UDP连接并将数据转换为自己的可读格式。它们是APR(Apache Portable Runtime),用于建立UDP连接并执行相关活动,XDR(外部数据表示)用于跨网络发送数据并执行RPC。

您需要首先在Java和Python中找到APR和XDR等效库。 XDR已经在Java中可用,APR可以由您自己的基本实现替换,以执行网络间操作(即创建UDP套接字等)。

打开神经节的gmond.c源文件,然后转到第1436行。您将找到一个C函数:

static void process_udp_recv_channel(const apr_pollfd_t *desc, apr_time_t now)

该功能基本上执行" UDP连接建立"和"数据翻译成可读格式"活动。

以上功能的呼叫流程如下所示:
Call flow

现在,让我们在第1436行展开这个功能以了解更多信息。

此函数中的第一个参数带有网络参数,如IP,端口等。结构在下面进行了扩展。您也可以在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重写它们。

然后,弄清楚收到的消息是否是&#34;元数据&#34;或&#34;指标值&#34;。

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编译器,其解释可在此question中找到。

注意:以下是gm_protocol_xdr.c的链接。

此处idenum,其声明如下所示:

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);

您可以在第275行的gm_protocol_xdr.c中找到此功能的完整扩展。

之后,您可以使用这些数据包执行任何操作。

最后,您必须释放所有分配的XDR变量和APR池。

我希望这可以让您从自己的应用程序开始。