Java Web 简单监控
Posted sp42a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Web 简单监控相关的知识,希望对你有一定的参考价值。
原理就是获取信息,然后解析并转化为目标结构信息输出。
监控包括下面几个维度:
- OS:CPU 利用率,CPU 温度,总内存大小,已使用内存大小
- JVM
- Tomcat
- 你的应用程序,包括异常信息
如何获取系统信息
获取方式各种各样,可综合使用:
- 系统的命令行,Java 用
runtime.exec()
函数获取之,或者封装一下 Shell 脚本 - Linux 提供的系统信息,通过文件管道获取之,例如
$ cat /proc/meminfo
- 对底层系统的调用和操作一般用 Java JNI 来完成,如 Sigar
- Java 自带的方法,如
System
类以及Runtime
和RuntimeMXBean
- oshi,偏向于硬件监控
系统的命令行
我找到一个 runtime.exec()
比较优秀的方法:
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* Create by yster@foxmail.com 2018/11/9 0009 22:28
*/
public class ExecuteCmd
/**
* 执行外部程序,并获取标准输出
*/
public static String execute(String[] cmd,String... encoding)
BufferedReader bufferedReader;
InputStreamReader inputStreamReader;
try
Process p = Runtime.getRuntime().exec(cmd);
/* 为"错误输出流"单独开一个线程读取之,否则会造成标准输出流的阻塞 */
Thread t = new Thread(new InputStreamRunnable(p.getErrorStream(), "ErrorStream"));
t.start();
/* "标准输出流"就在当前方法中读取 */
BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
if (encoding != null && encoding.length != 0)
inputStreamReader = new InputStreamReader(bis, encoding[0]);// 设置编码方式
else
inputStreamReader = new InputStreamReader(bis, "utf-8");
bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null)
sb.append(line);
sb.append("\\n");
bufferedReader.close();
p.destroy();
return sb.toString();
catch (Exception e)
e.printStackTrace();
return null;
Linux 提供的系统信息
获取 CPU 信息那个函数有点 Bug……这是代码出处:《JavaWeb 的监控系统》,说得不错。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
/**
*
* @author https://blog.csdn.net/hj7jay/article/details/51979939
*
*/
public class LinuxSystemTool
/**
* 内存的信息
*
* get memory by used info
*
* @return int[] result
* result.length==4;int[0]=MemTotal;int[1]=MemFree;int[2]=SwapTotal;int[3]=SwapFree;
* @throws IOException
* @throws InterruptedException
*/
public static int[] getMemInfo() throws IOException, InterruptedException
File file = new File("/proc/meminfo");
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
int[] result = new int[4];
String str = null;
StringTokenizer token = null;
while ((str = br.readLine()) != null)
token = new StringTokenizer(str);
if (!token.hasMoreTokens())
continue;
str = token.nextToken();
if (!token.hasMoreTokens())
continue;
if (str.equalsIgnoreCase("MemTotal:"))
result[0] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase("MemFree:"))
result[1] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase("SwapTotal:"))
result[2] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase("SwapFree:"))
result[3] = Integer.parseInt(token.nextToken());
br.close();
Arrays.toString(result);
return result;
/**
* get cpu by used info
*
* @return float efficiency
* @throws IOException
* @throws InterruptedException
*/
public static float getCpuInfo() throws IOException, InterruptedException
File file = new File("/proc/stat");
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
StringTokenizer token = new StringTokenizer(br.readLine());
token.nextToken();
int user1 = Integer.parseInt(token.nextToken());
int nice1 = Integer.parseInt(token.nextToken());
int sys1 = Integer.parseInt(token.nextToken());
int idle1 = Integer.parseInt(token.nextToken());
br.close();
Thread.sleep(1000);
br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
token = new StringTokenizer(br.readLine());
token.nextToken();
int user2 = Integer.parseInt(token.nextToken());
int nice2 = Integer.parseInt(token.nextToken());
int sys2 = Integer.parseInt(token.nextToken());
int idle2 = Integer.parseInt(token.nextToken());
br.close();
return (float) ((user2 + sys2 + nice2) - (user1 + sys1 + nice1)) / (float) ((user2 + nice2 + sys2 + idle2) - (user1 + nice1 + sys1 + idle1));
关于 Sigar
很多监控利用 Sigar 获取相关信息,例如 JeeSite 和这个开源项目 JMonitor 但是 Sigar 用起来比较麻烦:
Sigar有C,C#,Java和Perl API,java版的API为sigar.jar sigar.jar的底层是用C语言编写的,它通过本地方法来调用操作系统API来获取系统相关数据。Windows操作系统下Sigar.jar 依赖sigar-amd64-winnt.dll或sigar-x86-winnt.dll,linux 操作系统下则依赖libsigar-amd64-linux.so或libsigar-x86-linux.so
在这篇文章中,作者比较详细地介绍 Sigar 的用法,再结合上述资源,使用 Sigar 问题不大。但是我并不打算基于 Sigar 来做。
Java 自带的方法
- JVM 实时打印内存情况等,通过
ManagementFactory.getOperatingSystemMXBean()
和ManagementFactory.getRuntimeMXBean()
来实现监控 - Thread监控,通过
ManagementFactory.getThreadMXBean()
来实现监控 - GC 监控,通过
ManagementFactory.getGarbageCollectorMXBeans()
来实现监控
oshi (推荐)
相比 Sigar,oshi 不用自己添加依赖文件。
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.4.4</version>
</dependency>
- https://www.cnblogs.com/sundaboke/p/8493937.html
- https://blog.csdn.net/u012068483/article/details/104844143/
- https://zhuanlan.zhihu.com/p/149013115
- https://blog.csdn.net/weixin_43003720/article/details/111870418
其他高大上方法
- CAT
- Tomcat+Prometheus+Grafana
- Java Melody
参考
以上是关于Java Web 简单监控的主要内容,如果未能解决你的问题,请参考以下文章
[原创]java WEB学习笔记12:一个简单的serlet连接数据库实验