java tomcat 监控_java程序监控tomcat实现项目宕机自动重启并发送邮件提醒

最近由于老项目频繁挂掉,由于项目经过多批人之手,短时间难以定位问题,所以只好写一个监控程序。 时间比较紧半天时间,而且水平有限大神勿喷,有好的方法还请赐教。 1、问题描述:分两种情况1.1、tomcat 彻底挂掉端口不会占用进程;1.2、并没有彻底挂掉 端口仍占用进程,但是接口访问异常; 2、解决思路:启动一个java服务轮询(10秒钟一次)程序的一个接口(比如获取当前时间),如果请求不到则查看该端口是否占用进程,如果占用则杀死进程,然后重启tomcat ;如果没有占用进程则直接重启tomca; 本来考虑的是监控多个程序的 但是时间问题就先监控一个吧

3.1 轮训接口

@Service

public class SchedulerService {

private static final Logger logger = LoggerFactory.getLogger(SchedulerService.class);

@Autowired

private KillService killService;

@Value("#{system['jiankong.ports']}")

private String portsStr;

@Value("#{system['url']}")

private String url;

/**

* 监控接口是否通 如果接口不通 或者返回结果不对则重启服务 并发送邮件 每10秒执行一次扫描

* @author gaozemin

* @date 2017年10月18日

* @throws Exception

* @return

*/

public void watch() throws Exception {

String[] ports = portsStr.split(",");

for (String port : ports) {

// 调用测试接口

String ret = HttpUtil.sendPost(url, null);

if (ret == null) {// 如果返回结果为空重启服务

logger.info("返回结果为null ");

killService.start(Integer.valueOf(port));

} else {

try {

Map retMap = JSONObject.parseObject(ret, Map.class);

String retFlag = String.valueOf(retMap.get("result"));

if (!"200".equals(retFlag)) {// 如果返回结果异常 重启服务

killService.start(Integer.valueOf(port));

} else {

logger.info("系统运行正常....");

}

} catch (Exception e) {

logger.info("返回值解析异常....");

killService.start(Integer.valueOf(port));

}

}

logger.info("监控执行中..");

}

}

3.2 如果监控到异常则重启服务

@Service

public class KillService {

private static final Logger logger = LoggerFactory.getLogger(KillService.class);

@Value("#{system['waitTime']}")

private Long waitTime;

@Value("#{system['startTomcatExec']}")

private String startTomcatExec;

@Value("#{system['startLinuxTomcatExec']}")

private String startLinuxTomcatExec;

@Value("#{system['findPid']}")

private String findPid;

@Value("#{system['isLinux']}")

private boolean isLinux;

@Value("#{system['send.emails']}")

private String emails;

@Autowired

private SendMail sendMail;

private Map map = new HashMap();

public void start(int port) {

// 先每10秒 杀死一次进程 然后重启一次 ,执行重启后5分钟后再重新执行扫描,确保程序重新启动

// 1 获取 指定端口的进程号

// 如果调用接口失败则杀死进程并重新启动 ,并记录当前时间 ,否则不进行操作

Date lastExecTime = map.get(port);

if (lastExecTime != null) {// 如果存在重启记录则判断重启时间是否间隔5分钟

Date nowTome = new Date();

Long subTime = nowTome.getTime() - lastExecTime.getTime();

logger.info("间隔时间:{}", subTime);

if (subTime < waitTime) {

logger.info("间隔时间过短 等待程序启动!");

return;

} else {

map.put(port, new Date());

restartTomcat(port, isLinux);

}

} else {

map.put(port, new Date());

restartTomcat(port, isLinux);

}

}

private void restartTomcat(int port, boolean isLinux) {

Runtime runtime = Runtime.getRuntime();

try {

if (isLinux) {

// 查找进程号

linuxRestart(port);

StartTomcatThread a = new StartTomcatThread(startLinuxTomcatExec);

a.start();

} else {

Process p = runtime.exec(findPid + port);

InputStream inputStream = p.getInputStream();

List read = read(port, inputStream, "UTF-8");

if (read.size() == 0) {

logger.info("找不到端口:{}的进程", port);

StartTomcatThread a = new StartTomcatThread(startTomcatExec);

a.start();

logger.info("tomcat已重启");

} else {

logger.info("找到" + read.size() + "个进程,正在准备清理");

kill(read);

StartTomcatThread a = new StartTomcatThread(startTomcatExec);

a.start();

}

}

String dataStr = "admin 服务宕机 现已自动重启 请及时查看日志 修改错误!";

String[] emailStrs = emails.split(",");

for (String email : emailStrs) {

sendMail.sendMsg(email, dataStr);

}

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 验证此行是否为指定的端口,因为 findstr命令会是把包含的找出来,例如查找80端口,但是会把8099查找出来

*

* @param str

* @return

*/

private boolean validPort(int port, String str) {

String patternString = "^ *[a-zA-Z]+ +\\S+";

Pattern pattern = Pattern.compile(patternString);

Matcher matcher = pattern.matcher(str);

matcher.find();

String find = matcher.group();

int spstart = find.lastIndexOf(":");

find = find.substring(spstart + 1);

int findport = 0;

try {

findport = Integer.parseInt(find);

} catch (NumberFormatException e) {

System.out.println("查找到错误的端口:" + find);

return false;

}

if (port == findport) {

return true;

} else {

return false;

}

}

public void linuxRestart(int port) throws IOException, InterruptedException {

String cmd = "kill -9 $(netstat -tlnp|grep " + port + "|awk '{print $7}'|awk -F '/' '{print $1}')";

String[] command = { "sh", "-c", cmd };

Process pro = Runtime.getRuntime().exec(command);

pro.waitFor();

// cmd = path;

// pro = Runtime.getRuntime().exec(cmd);

// pro.waitFor();

}

/**

* 更换为一个Set,去掉重复的pid值

*

* @param data

*/

public void kill(List data) {

Set pids = new HashSet<>();

logger.info("列表:{}" + pids);

for (String line : data) {

int offset = line.lastIndexOf(" ");

String spid = line.substring(offset);

spid = spid.replaceAll(" ", "");

int pid = 0;

try {

pid = Integer.parseInt(spid);

} catch (NumberFormatException e) {

System.out.println("获取的进程号错误:" + spid);

}

pids.add(pid);

}

killWithPid(pids);

}

/**

* 一次性杀除所有的端口

*

* @param pids

*/

public void killWithPid(Set pids) {

for (Integer pid : pids) {

try {

Process process = Runtime.getRuntime().exec("taskkill /F /pid " + pid + "");

InputStream inputStream = process.getInputStream();

String txt = readTxt(inputStream, "UTF-8");

logger.info(txt);

} catch (IOException e) {

e.printStackTrace();

}

}

}

private List read(int port, InputStream in, String charset) throws IOException {

List data = new ArrayList<>();

BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));

String line;

while ((line = reader.readLine()) != null) {

boolean validPort = validPort(port, line);

if (validPort) {

data.add(line);

}

}

reader.close();

return data;

}

public String readTxt(InputStream in, String charset) throws IOException {

BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));

StringBuffer sb = new StringBuffer();

String line;

while ((line = reader.readLine()) != null) {

sb.append(line);

}

reader.close();

return sb.toString();

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383011.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java静态类和非静态类的区别_Java中静态内部类和非静态内部类到底有什么区别?...

内部类(Inner Class)和静态内部类(Static Nested Class)的区别&#xff1a;定义在一个类内部的类叫内部类&#xff0c;包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制&#xff0c;可以声明 为abstract的供其他内部类或外部类继承与扩展&#x…

java写便签_如何编写一个便签程序(用Java语言编写)

如何编写一个便签程序(用Java语言编写)热度&#xff1a;336 发布时间&#xff1a;2011-02-18 11:44:16如何编写一个便签程序(用Java语言编写)因为以前没有好好学习Java&#xff0c;都搞忘了&#xff0c;请大家原谅&#xff0c;也请你们指导一下&#xff0c;怎么编写这个程序&…

java 生成log4j_Java log4j配置每天生成一个日志文件 - 永恒ぃ☆心 的日志 - 网易博客...

一、配置属性文件log4j.propertieslog4j.rootLoggerINFO,stdout,Rlog4j.appender.stdoutorg.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layoutorg.apache.log4j.PatternLayout# Pattern to output the callers file name and line number.log4j.appender.stdout.layo…

java 子进程输出流_具有输入/输出流的Java进程

首先&#xff0c;我建议更换这条线路。Process process Runtime.getRuntime ().exec ("/bin/bash");带着线条ProcessBuilder builder new ProcessBuilder("/bin/bash");builder.redirectErrorStream(true);Process process builder.start();ProcessBuil…

java中if 运算符_[Java]Java基本语法结构(运算符,流程控制语句,if语句)

1:运算符(掌握)(1)算术运算符A:,-,*,/,%,,--B:的用法a:加法b:正号c:字符串连接符C:/和%的区别数据做除法操作的时候&#xff0c;/取得是商&#xff0c;%取得是余数D:和--的用法a:他们的作用是自增或者自减b:使用**单独使用放在操作数据的前面和后面效果一样。a或者a效果一样。*…

java 变量取值范围_JAVA中的变量及取值范围

字节是二进制数据的单位。一个字节通常8位长。但是&#xff0c;一些老型号计算机结构使用不同的长度。为了避免混乱&#xff0c;在大多数国际文献中&#xff0c;使用词代替byte。变量&#xff1a;变量的数据类型&#xff1b;变量名变量值数据类型基本型数值型(整数)布尔型浮点型…

java object强制类型转换_scala object 转Class Scala强制类型转换

asInstanceOf[T]将对象类型强制转换为T类型。还是由于泛型存在类型擦除的原因,1.asInstanceOf[String]在运行时会抛出ClassCastException异常&#xff0c;而List(1).asInstanceOf[List[String]]将不会。packageresti.webimportorg.springframework.beans.factory.annotation.Au…

java毛玻璃_模糊效果(毛玻璃效果)

模糊效果(毛玻璃效果)效果演示&#xff1a;1. 使用iOS自带的 UIImageImageEffects 文件文件中有这么几个方法&#xff1a;- (UIImage *)applyLightEffect;- (UIImage *)applyExtraLightEffect;- (UIImage *)applyDarkEffect;- (UIImage *)applyTintEffectWithColor:(UIColor *)…

java程序崩溃怎么重启_android 异常崩溃后 重启app(进程守护方式实现)

【实例简介】【实例截图】【核心代码】package com.sunfusheng.daemon.sample;import android.content.ComponentName;import android.content.Intent;import android.os.Looper;import android.util.Log;import com.blankj.utilcode.util.AppUtils;import com.sunfusheng.daem…

mysql 存储过程 循环结构 命名_mysql存储过程----循环结构

循环结构一共分为三种&#xff1a;三种循环结构分别为while、repeat、loop。while循环语法while 表达式(如果表达式为true则执行业务逻辑&#xff0c;否则不执行&#xff0c;与repeat循环相反&#xff0c;repeat循环满足表达式退出循环&#xff0c;不满足一直执行) do业务逻辑e…

mysql 组合索引 or_Mysql_组合索引和单列索引

一、目标什么时候使用组合索引&#xff0c;什么时候使用单独索引组合索引、单独索引区别组合索引&#xff1a;最左前缀匹配原则二、前期数据准备1. 建表CREATE TABLE user (uidint(11) NOT NULLAUTO_INCREMENT,namevarchar(50) DEFAULT NULL,pwdvarchar(50) DEFAULT NULL,creat…

mysql与mangodb多租户_MongoDB多租户(Java):如何使用MongoClient在运行时切换具有不同数据库凭据的MongoDB数据库?...

我正面临一个关于MongoDB多租户的问题.我有两个不同的mongoDB数据库(db1和db2).这两者都有不同的凭据.db1凭据&#xff1a;userName&#xff1a;admin密码&#xff1a;passwddb2凭据&#xff1a;userName&#xff1a;admin1密码&#xff1a;passwd1我需要在运行时从一个数据库切…

python 库 全局变量_python局部变量和全局变量global

当你在函数定义内声明变量的时候&#xff0c;它们与函数外具有相同名称的其他变量没有任何关系&#xff0c;即变量名称对于函数来说是 局部 的。这称为变量的 作用域 。所有变量的作用域是它们被定义的块&#xff0c;从它们的名称被定义的那点开始。使用局部变量例7.3 使用局部…

java 自省_自知 自省 自立 自信 自尊 自治 自强 自制

自知 自省 自立 自信 自尊 自治 自强 自制能知人者有智力&#xff0c;能自知才是真正的智者&#xff1b;能战胜别人者有力量&#xff0c;能战胜自己才是真正的强者&#xff1b;能知足者就是富有&#xff0c;能勤奋顽强坚持才是真正的有志者&#xff1b;不失其立足之地的人可以长…

java中json重复数据结构_JAVA把各种数据结构转换为JSON格式

Java代码import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import net.sf…

字节字符区别Java_【JAVA基础】字符数组与字节数组的区别

String.getBytes()和String.tocharArray()&#xff0c;字节数组和字符数组的区别String.getBytes()是将字符串转化为一个字节数组。而String.toCharArray()是将一个字符串转化为一个字符数组。【例如】byte bys[] “国庆60周年”.getBytes();char chs[]“国庆60周年”.toCharAr…

mysql日志管理_关于MySQL的日志管理(binlog)

关于MySQL的日志管理(binlog)一、查看binlog的启用状态最常用的mysql版本是5.7&#xff0c;默认不开启binlog&#xff0c;可以在登录mysql之后&#xff0c;利用以下命令查看当前的binlog启用状态&#xff1a;mysql show variables like "%log_bin%";图中显示“ON”&a…

java精确测量文本高度_基于文本精确计算UITableViewCell的高度

我正在开发一个ios应用程序&#xff0c;并使用autolayout我正在尝试创建一个具有不同行高的表视图 .原型单元的布局如下&#xff1a;我有一个主单元格(黑色)里面有一个UIView(红色)&#xff0c;里面有一个UILabel(蓝色)我添加的Autolayout约束如图所示&#xff1a;The UIView h…

php做一个微信退款,PHP实现微信退款功能

大家好&#xff0c;我是小编&#xff0c;最近在调微信退款接口&#xff0c;发现有许多坑&#xff0c;更大家分享一下① 要是在测试的时候&#xff0c;网页提示 curl 58 说明 证书的路径出现问题(这里要填物理路径&#xff0c;也就是绝对路径)②网页提示curl 52 说明你的证书引入…

php显示时间,php实现用已经过去多长时间的方式显示时间

本文实例讲述了php用已经过去多长时间的方式显示时间的方法。分享给大家供大家参考。具体如下&#xff1a;这里以一种可读性比较好的方式显示已经过去多长时间&#xff0c;比如&#xff1a;距离现在10秒&#xff0c;距离现在1天等等。function time_is_older_than($t, $check_t…