简体   繁体   English

确保弹簧靴和 liquibase 接收并处理 SIGTERM

[英]Ensuring spring boot and liquibase receive and handle SIGTERM

Currently running SpringBoot applications in a containerised environment (ECS) and I've observed scenarios in which the container gets terminated during start-up and while it's still holding the Liquibase changelock.目前在容器化环境 (ECS) 中运行 SpringBoot 应用程序,我观察到容器在启动期间终止并且仍然持有 Liquibase 变更锁的情况。

This leads to issues in all containers that are spun afterwards and ends up requiring manual intervention.这会导致随后旋转的所有容器出现问题,最终需要手动干预。

Is it possible to ensure that if the process receives a SIGTERM, it will gracefully handle termination and release the lock?是否可以确保如果进程收到 SIGTERM,它将优雅地处理终止并释放锁?

I've already ensured that the container is receiving the signals by enabling via InitProcessEnabled (in the CloudFormation template) and use of "exec java ..." as a java agent we use does gracefully shutdown on this circumstances.我已经通过 InitProcessEnabled(在 CloudFormation 模板中)启用并使用“exec java ...”作为我们使用的 java 代理来确保容器正在接收信号,在这种情况下会正常关闭。

Heyo,嘿嘿

As mentioned in the GitHub issue I have a workaround.正如 GitHub 问题中提到的,我有一个解决方法。 A solution is yet to be implemented.尚未实施解决方案。

You can manually register a shutdown hook before running spring boot.. That hook should assure that the Termination is postponed until liquibase is done.您可以在运行 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);
  }
}

And the hook:和钩子:

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;
              }
            }
          }
        }
      }
    }
  }
}

EDIT编辑

After implementing my workaround a contributor of liquibase shared a different solution (It's actually the same solution just through Spring functionality) which is much better than what I did:在实施我的解决方法后,liquibase 的贡献者共享了一个不同的解决方案(它实际上是通过 Spring 功能实现的相同解决方案),这比我所做的要好得多:

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 {
    new SpringApplicationBuilder(DangApplication.class)
            .initializers(ConfigurableApplicationContext::registerShutdownHook) // Registers application hook before liquibase executes.
            .logStartupInfo(true)
            .build()
            .run();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM