ellios's blog

ellios's trivial story.

Ganglia整合java

| Comments

前段时间简单介绍了Ganglia的安装和配置,现在我们的Ganglia已经跑了起来,并且已经可以展示机器的负载, 网络,io等各种数据,但是光有机器的情况还是远远不够,我们还需要了解每个应用的运行情况。针对一些常见的应用如:Mysql,Memcached,Redis,Nginx等,Ganglia的github上有很多开源的模块,大家可以自己折腾,要是有时间,后面也会简单简介绍下。这里主要介绍下怎么用Ganglia来收集和展示Java的数据,包括JVM的运行数据和业务数据。

获取JMX数据

JVM的运行数据我们是从JMX获得的,其实业务数据也可以写进JMX里,所以如果你的Java应用开启了JMX的话,基本上各种数据都可以从JMX中获得了。获取JMX数据的包Ganglia的网站已经有了,叫jmxetric。要使用它,需要再jvm参数里加入如下的内容

1
-javaagent:jmxetric-1.0.3.jar=host=xxx,port=xxx,mode=unicast,wireformat31x=true,config=jmxetric.xml

host是接收数据gmond的host,port是gmond的端口,mode有multicast和unicast两种,由于网络原因,我们使用的是unicast(单播),wireformat31x这个不清楚,一直都是true来着。前面几项配置都可以写到jmxetric.xml里面,不过为了方便控制这些参数,放到了外面。jmxetric.xml里面写需要获取的JMX的数据项,jmxetric的站点上有各详细的示例,这个不不再占用空间了。

一些注意的地方: 1. jmxetric.jar还依赖与gmetric4j.jar和oncrpc.jar,所以如果是直接下载jar包的话,要把依赖的jar包也都下到,而且要和jmxetric.jar在一个目录下。我们的项目是用maven管理的,直接加如下的依赖

1
2
3
4
5
<dependency>
    <groupId>info.ganglia.jmxetric</groupId>
    <artifactId>jmxetric</artifactId>
    <version>1.0.3</version>
</dependency>
  1. 记得开启JMX哦

直接发送数据

如果觉得从JMX获取数据麻烦的话,或者你不想开启JMX,你也可以直接发送数据到gmond。这个也有了现成的包gmetric4j,其实jmxetric也是利用他来发送数据的。这个没啥好说的,就是利用包提供的api发送数据就好了。 写了一个工具类,对原生的api做了简单的封装。最近看了下yammer开源的metrics,很强大,有兴趣的可以看下它的源码。

Ganglia Monitor Util MonitorUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import info.ganglia.gmetric4j.gmetric.GMetric;
import info.ganglia.gmetric4j.gmetric.GMetricSlope;
import info.ganglia.gmetric4j.gmetric.GMetricType;
import info.ganglia.gmetric4j.gmetric.GangliaException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MonitorUtil {

    private static final Logger logger = LoggerFactory.getLogger(MonitorUtil.class);
    private static final HedwigConfig HC = HedwigConfig.getInstance();

    private static class GMetricHOlder {
        static String GANGLIA_HOST = HC.getString("ganglia.host", "");
        final static int GANGLIA_PORT = HC.getInt("ganglia.port", 7649);
        final static int GANGLIA_TTL = HC.getInt("ganglia.ttl", 1);
        static {
            if(StringUtils.isEmpty(GANGLIA_HOST)){
                GANGLIA_HOST = NetworkUtils.getEth0Address();
            }
            System.out.println("[GANGLIA MONITOR] begin to init gmetric");
            System.out.println("[GANGLIA MONITOR] GANGLIA_HOST : " + GANGLIA_HOST);
            System.out.println("[GANGLIA MONITOR] GANGLIA_PORT : " + GANGLIA_PORT);
            System.out.println("[GANGLIA MONITOR] GANGLIA_TTL : " + GANGLIA_TTL);
        }
        final static GMetric G_METRIC = new GMetric(GANGLIA_HOST, GANGLIA_PORT,
                GMetric.UDPAddressingMode.UNICAST, GANGLIA_TTL, true);
    }

    private static GMetric getGMetric() {
        return GMetricHOlder.G_METRIC;
    }

    /**
     * monitor a metric
     * @param name Name of the metric
     * @param value Value of the metric
     * @param type Type of the metric.  
     *        Either string|int8|uint8|int16|uint16|int32|uint32|float|double
     * @param units Unit of measure for the value
     * @param slope Either zero|positive|negative|both
     * @param group Group Name of the metric
     */
    public static void monitor(String name, String value, GMetricType type,
                               String units,  GMetricSlope slope, String group) {
        GMetric gm = getGMetric();
        try {
            gm.announce(name, value, type, units, slope, 60, 0,  group);
        } catch (GangliaException e) {
            logger.error("monitor fail. name : {}, value:{}, error:{}",
            name, value, e.getMessage(), e);
        }

    }

    /**
     * monitor a metric
     * @param name Name of the metric
     * @param value Value of the metric
     * @param group Group Name of the metric
     */
    public static void monitor(String name,  String value, String group){
        monitor(name, value, GMetricType.STRING, " ", GMetricSlope.BOTH, group);
    }

    /**
     * monitor a positive metric
     * @param name Name of the metric
     * @param value Value of the metric
     * @param group Group Name of the metric
     */
    public static void counter(String name,  String value, String group){
        monitor(name, value, GMetricType.STRING, " ", GMetricSlope.POSITIVE, group);
    }

    /**
     * monitor a metric
     * @param name Name of the metric
     * @param value Value of the metric
     * @param group Group Name of the metric
     */
    public static void monitor(String name,  float value, String group){
        monitor(name, Float.toString(value),GMetricType.DOUBLE, " ", GMetricSlope.BOTH, group);
    }

    /**
     * monitor a positive metric
     * @param name Name of the metric
     * @param value Value of the metric
     * @param group Group Name of the metric
     */
    public static void counter(String name, float value, String group){
        monitor(name, Float.toString(value),GMetricType.FLOAT, " ", GMetricSlope.POSITIVE, group);
    }

}

参考资料

Comments