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.pswp.cn/news/383011.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383011.shtml
英文地址,請注明出處:http://en.pswp.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…