Эластичный бобовый стебель - изящное завершение слишком короткое - PullRequest
1 голос
/ 01 июля 2019

Я пытаюсь выполнить постепенное завершение работы приложения эластичного бобового стебля, и я собрал этот тест выключения -

Main-

public class Main {

    public static void main(String[] args) throws InterruptedException {
        ShutdownTest shutdownTest = new ShutdownTest();
        shutdownTest.run();

        System.out.println("END OF MAIN");
    }
}

Тестовый класс-

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ShutdownTest {

    private volatile long jobEnd;
    private volatile boolean shutdown = false;

    public void run() throws InterruptedException {

        Thread mainThread = Thread.currentThread();

        Thread shutdownHook = new Thread(() -> {
            runShutdownTimer();

            try {
                System.out.println("Got shutdown signal.");

                shutdown = true;

                mainThread.join();
            } catch(Exception e) {
                System.out.println(e);
            }
        });

        Runtime.getRuntime().addShutdownHook(shutdownHook);

        while(!shutdown) {
            long jobStart = System.currentTimeMillis();
            int jobRunTime = 60000;
            jobEnd = jobStart + jobRunTime;
            Thread.sleep(jobRunTime);
        }


        System.out.println("End of Run");
    }

    public void runShutdownTimer() {
        long start = System.currentTimeMillis();
        float waitTime = (jobEnd - start)/1000f;

        System.out.println("Shutdown phase should take " + waitTime + " seconds");

        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.execute(() -> {
            while(true) {
                long now = System.currentTimeMillis();
                float diff = (float)(now - start)/1000f;

                System.out.println(diff + " seconds elapsed in shutdown phase");

                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Если я запускаю это локально и отправляю сигнал выключения (^ C или прекращение выполнения через мою IDE), я получу вывод, подобный-

Shutdown phase should take 45.139 seconds
Got shutdown signal.
0.006 seconds elapsed in shutdown phase
0.311 seconds elapsed in shutdown phase
0.615 seconds elapsed in shutdown phase
...
44.433 seconds elapsed in shutdown phase
44.734 seconds elapsed in shutdown phase
45.035 seconds elapsed in shutdown phase
End of Run
END OF MAIN
<END OF EXECUTION>

Но если я запусту это на Elastic Beanstalk и отправлю сигнал выключения нажатием новой версии, я получу что-то вроде этого -

Shutdown phase should take 25.647 seconds
Got shutdown signal.
0.007 seconds elapsed in shutdown phase
0.307 seconds elapsed in shutdown phase
0.607 seconds elapsed in shutdown phase
...
9.614 seconds elapsed in shutdown phase
9.915 seconds elapsed in shutdown phase
10.215 seconds elapsed in shutdown phase
<END OF EXECUTION>

Я делал это пару раз, и кажется, что выполнение принудительно завершается примерно через 10 секунд, независимо от того, сколько времени он должен ждать. Задания, выполняемые этими приложениями, могут занимать более 10 секунд, полагаясь на сеть и запрашивая скорости внешних сил, которые не поддаются контролю.

Есть ли способ увеличить тайм-аут принудительного завершения?

Edit:

Я пробовал заскочить в коробку и убить процесс через pkill java (без сигнала). Журналы показывают, что приложение успешно прошло 28-секундный процесс завершения работы. Что-то в службе эластичного бобового стебля, как я и подозревал, выдает вторую сигтерму. Я обновлюсь, когда выясню, что это такое.

Редактировать Редактировать:

Я изучил хуки жизненного цикла ASG. Они работают, испуская событие cloudwatch, когда начинается событие завершения. Это событие содержит идентификатор экземпляра ec2 и может быть отправлено в / направлено темой SNS. Когда перехватчики жизненного цикла ASG настроены на отправку подобных событий, он будет ожидать подтверждения того, что завершение может продолжаться с настраиваемым периодом ожидания. Это означает, что каждый EC2 в ASG может прослушивать эту тему SNS для своего собственного события завершения, запустить процедуру выключения, а затем предупредить ASG о том, что процесс завершения может продолжиться.

Это может работать для масштабирования, но не будет работать при обновлении среды EC2 - вызывая перезапуск приложения.

...