Java Tomcat自动重启实现指南
一 系统级守护与自恢复
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Environment=CATALINA_PID=/opt/tomcat9/temp/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat9
Environment=CATALINA_BASE=/opt/tomcat9
Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'
ExecStart=/opt/tomcat9/bin/startup.sh
ExecStop=/opt/tomcat9/bin/shutdown.sh
User=tomcat
Group=tomcat
UMask=0007
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
二 定时重启
#!/bin/bash
source /etc/profile
export JAVA_HOME=/usr/local/jdk
export JRE_HOME=$JAVA_HOME/jre
TOMCAT_HOME=/opt/tomcat
LOGFILE=/opt/log/restart_tomcat.log
echo "[$(date '+%F %T')] 停止 Tomcat ..." >> $LOGFILE
$TOMCAT_HOME/bin/shutdown.sh >> $LOGFILE 2>&1
sleep 5
# 兜底强杀残留进程
PID=$(ps -ef | grep java | grep catalina | awk '{print $2}')
if [ -n "$PID" ]; then
kill -9 $PID && echo "[$(date '+%F %T')] 已 kill 进程 $PID" >> $LOGFILE
fi
sleep 2
echo "[$(date '+%F %T')] 启动 Tomcat ..." >> $LOGFILE
$TOMCAT_HOME/bin/startup.sh >> $LOGFILE 2>&1
三 应用内或外部监控自愈
public class TomcatWatchdog {
private static final String HEARTBEAT_URL = "http://localhost:8080/heartbeat.htm";
private static final int CONNECT_TIMEOUT = 1000;
private static final int READ_TIMEOUT = 4000;
private static final String TOMCAT_HOME = "/opt/tomcat";
public static void main(String[] args) throws Exception {
if (!isAlive(HEARTBEAT_URL)) {
System.out.println(new Date() + " 心跳失败,检查进程并准备重启");
if (isProcessAlive("catalina")) {
System.out.println(new Date() + " 进程仍在,先尝试关闭");
exec(TOMCAT_HOME + "/bin/shutdown.sh");
Thread.sleep(5000);
if (isProcessAlive("catalina")) {
System.out.println(new Date() + " 关闭失败,执行 kill -9");
exec("kill -9 $(ps -ef | grep java | grep catalina | awk '{print $2}')");
Thread.sleep(2000);
}
}
System.out.println(new Date() + " 启动 Tomcat");
exec(TOMCAT_HOME + "/bin/startup.sh");
}
}
private static boolean isAlive(String url) {
try {
URL u = new URL(url);
URLConnection c = u.openConnection();
c.setConnectTimeout(CONNECT_TIMEOUT);
c.setReadTimeout(READ_TIMEOUT);
try (BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()))) {
while (in.readLine() != null) { }
}
return true;
} catch (Exception e) { return false; }
}
private static boolean isProcessAlive(String keyword) throws Exception {
Process p = Runtime.getRuntime().exec("ps -ef | grep java | grep " + keyword);
try (BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
return r.lines().anyMatch(l -> l.contains(keyword));
}
}
private static void exec(String cmd) throws Exception {
Process p = Runtime.getRuntime().exec(cmd);
try (BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
r.lines().forEach(System.out::println);
}
}
}
四 运维与部署常用方式
五 关键注意事项
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。