确保spring boot和liquibase接收并处理SIGTERM

时间:2019-05-02 14:26:07

标签: java spring-boot docker liquibase amazon-ecs

当前在容器化环境(ECS)中运行SpringBoot应用程序,并且我观察到了以下情况:容器在启动过程中终止,而它仍然保持Liquibase changelock。

这会导致所有随后旋转的容器出现问题,最终需要人工干预。

是否可以确保如果进程收到SIGTERM,它将正常处理终止并释放锁?

我已经确保通过InitProcessEnabled(在CloudFormation模板中)启用容器并使用“ exec java ...”作为我们使用的Java代理在这种情况下正常关闭,从而确保容器正在接收信号。

1 个答案:

答案 0 :(得分:0)

Heyo,

正如GitHub问题中所述,我有一个解决方法。解决方案尚未实现。

您可以在运行spring boot之前手动注册一个关闭钩子。该钩子应确保终止终止,直到完成liquibase。

package dang;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;


@EnableJpaRepositories
@SpringBootApplication
public class DangApplication {
  public static void main(String[] args) throws InterruptedException {
    Thread thread = new GracefulShutdownHook();
    Runtime.getRuntime().addShutdownHook(thread);

    new SpringApplicationBuilder(DangApplication.class)
            .registerShutdownHook(true)
            .logStartupInfo(true)
            .build()
            .run();
    Runtime.getRuntime().removeShutdownHook(thread);
  }
}

还有挂钩:

package dang;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@Slf4j
public class GracefulShutdownHook extends Thread {
  @SneakyThrows
  @Override
  public void run() {


    super.run();
    log.info("Shutdown Signal received.. Searching for Liquibase instances!");
    boolean liquibaseIsRunning = true;
    while (liquibaseIsRunning) {

      Map<Thread,StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
      for(Map.Entry<Thread, StackTraceElement[]> entry : stackTraces.entrySet()) {
        StackTraceElement[] stackTraceElements = entry.getValue();
        for (StackTraceElement stackTraceElement : stackTraceElements) {
          if (stackTraceElement.getClassName().contains("liquibase") && stackTraceElement.getMethodName().contains("update")) {
            try {
              log.warn("Liquibase is currently updating");
              entry.getKey().join();
              liquibaseIsRunning = false;
            } catch (InterruptedException e) {
              log.error("Shutdown Hook was interrupted.. Fatal databaselock may be imminent", e);
              if (Thread.interrupted()) {
                throw e;
              }
            }
          }
        }
      }
    }
  }
}