最近开发遇到一个需要网络检测的场景,具体是需要实时(或者近乎实时吧)的监测本级单位与下级单位的网络连通情况并做可视化呈现,所以想到在服务器开一个定时任务,每隔一段时间就去轮询一遍各单位服务器的连通状态存储后供前段呈现,查阅一些资料后总结后台网络检测可选方案有两种
1.使用Java API的InetAddress方式(有坑,不推荐)
自Java 1.5开始,java.net包中就实现了ping的功能。详见InetAddress.isReachable()方法。具体代码如下
public static boolean ping(String ipAddress) throws Exception {
int timeOut = 3000 ; //超时应该在3钞以上
boolean status = InetAddress.getByName(ipAddress).isReachable(timeOut);
// 当返回值是true时,说明host是可用的,false则不可。
return status;
}
经过测试,该方法有先天不足,在测试baidu.com服务器时,就出现了从系统能ping通但该方法返回false的情况,百度一番后了解到root用户运行该方法会使用ping命令探测. 如果普通用户不携带特权会探测tcp7端口,如果7端口安全组不开启会与预期结果不一致,所以就造成了上面的情况。所以运行该方法必须以root方式最为保险。
2.直接粗暴调用系统command进行ping检测(通俗易懂稳定,推荐)
ping命令是操作系统中最常见的一个检测网络的命令,所以我们只需要调用系统ping指定地址,通过分析返回情况就可以判断网络是否通联,当然前提是防火墙没有禁ping,具体实现代码
/**
* 检测服务器连通性的可靠办法
* InetAddress.isReachable 是不靠谱的
* ping -c 1 -W 1是1秒钟如果ping 不到就超时
* @param hostname
* @return
*/
public static final boolean isServerReachable(String hostname) {
try {
return 0==Runtime.getRuntime().exec("ping -c 1 -W 3 "+hostname).waitFor();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
return false;
}
}
这里需要说明的是如果单纯的使用“ping -c 1”来检测,如果服务器不在线就会一直等到超时,可能时间会比较长,不利于做实时检测,所以可以根据实际情况在后面加上“-w”参数来指定超时时间,-w 1就是等待1秒,这样就能满足大部分的应用场景。
3.前端展示
本项目的具体构架是后端sping boot 开启一个定时任务轮询服务器状态,并将结果保存在一个全局表中,用户端可通过调用指定api返回检测结果,前端使用的是leaflet地图框架,通过定时器向后台拉取网络连状况,并解析结果按服务器地理位置,以不同颜色的线段将网络连接状态叠加至地图上,实现可视化呈现。
|