Springboot优雅停止程序

1、添加actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、自定义actuator关停代码

@Endpoint(
        id = "myShutdown",
        enableByDefault = false
)
@Component
@Slf4j
public class MyShutdownEndpoint implements ApplicationContextAware{
    private static final Map<String, String> NO_CONTEXT_MESSAGE = Collections.unmodifiableMap(Collections.singletonMap("message", "No context to shutdown."));
    private static final Map<String, String> SHUTDOWN_MESSAGE = Collections.unmodifiableMap(Collections.singletonMap("message", "Shutting down, bye..."));
    private ConfigurableApplicationContext context;

    public MyShutdownEndpoint() {
    }

    @WriteOperation
    public Map<String, String> shutdown() {
        if (this.context == null) {
            return NO_CONTEXT_MESSAGE;
        } else {
            boolean var6 = false;

            Map var1;
            try {
                //在停止程序前,先停止自定义的模块代码。
                String modules = ConfigurationHolder.getSystemParamFromFile(GlobalConstant.MODULE_CODE, "");
                if (Tools.isNotEmptyStr(modules)) {
                    String[] moduleArr = modules.split(",");
                    SignalModule module;
                    for (String moduleName : moduleArr) {
                        module = (SignalModule) context.getBean(moduleName);
                        module.stopModule();
                        log.info("模块{}已停止",moduleName);
                    }
                }
                var6 = true;
                var1 = SHUTDOWN_MESSAGE;
                var6 = false;
            } finally {
                if (var6) {
                    Thread thread = new Thread(this::performShutdown);
                    thread.setContextClassLoader(this.getClass().getClassLoader());
                    thread.start();
                }
            }

            Thread thread = new Thread(this::performShutdown);
            thread.setContextClassLoader(this.getClass().getClassLoader());
            thread.start();
            return var1;
        }
    }

    private void performShutdown() {
        try {
            Thread.sleep(500L);
        } catch (InterruptedException var2) {
            Thread.currentThread().interrupt();
        }

        this.context.close();
    }

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        if (context instanceof ConfigurableApplicationContext) {
            this.context = (ConfigurableApplicationContext)context;
        }

    }
}

3、配置properties文件

# 利用actuator优雅停止程序
management.endpoint.health.show-details=always
# 原启用shutdown配置
# management.endpoint.shutdown.enabled=true
#自定义启用myShutdown配置
management.endpoint.myShutdown.enabled=true
management.health.redis.enabled=false
management.health.db.enabled=false
management.endpoints.web.exposure.include=*
# 自定义管理断点的前缀,安全性考虑
management.endpoints.web.base-path=/actuator
# 自定义端口
management.server.port=18081
# 不允许远程管理连接,安全性考虑
management.server.address=127.0.0.1

4、本地测试

成功后会输出:{"message":"Shutting down, bye..."}

5、附shell脚本启动与停止

#!/bin/bash
#这里可替换为你自己的执行程序,其他代码无需更改
APP_NAME=demoApp
APP_JAR=demoApp-1.0-RELEASE.jar
 
#使用说明,用来提示输入参数
usage() {
    echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"
    exit 1
}
 
#检查程序是否在运行
is_exist(){
  pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
  #如果不存在返回1,存在返回0     
  if [ -z "${pid}" ]; then
   return 1
  else
    return 0
  fi
}
 
#启动方法
start(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is already running. pid=${pid} ."
  else
    nohup /home/jdk1.8.0_161/bin/java -D$APP_NAME -jar $APP_JAR > logs/demoApp.log 2>&1 &
    status
    tail -f logs/demoApp.log
  fi
}
 
#停止方法
stop(){
  is_exist
  if [ $? -eq "0" ]; then
   curl -X POST http://127.0.0.1:18081/actuator/myShutdown
   httpode="$(curl -sL -w '%{http_code}' http://127.0.0.1:18081/actuator/myShutdown -o /dev/null)";
   while [ "${httpCode}" != "000" ]
   do
   	 httpCode="$(curl -sL -w '%{http_code}' http://127.0.0.1:18081/actuator/myShutdown -o /dev/null)"
   done
   sleep 5
   kill -9 $pid
   echo "${APP_NAME} is stop success"
  else
    echo "${APP_NAME} is not running"
  fi  
}
 
#输出运行状态
status(){
  is_exist
  if [ $? -eq "0" ]; then
    echo "${APP_NAME} is running. Pid is ${pid}"
  else
    echo "${APP_NAME} is NOT running."
  fi
}
 
#重启
restart(){
  stop
  start
}
 
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
  "start")
    start
    ;;
  "stop")
    stop
    ;;
  "status")
    status
    ;;
  "restart")
    restart
    ;;
  *)
    usage
    ;;
esac

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值