Запретить закрытие приложения Spring Boot, пока все текущие запросы не будут завершены - PullRequest
6 голосов
/ 17 мая 2019

У нас есть приложение Spring Boot (2.0.4), предоставляющее ряд конечных точек, одна из которых позволяет клиентам извлекать иногда очень большие файлы (~ 200 ГБ).Приложение предоставляется в Pod через развертывание Kubernetes, настроенное с помощью стратегии скользящего обновления.

Когда мы обновляем наше развертывание, устанавливая образ на последнюю версию, модули уничтожаются, а новые запускаются.Предоставление наших услуг является бесшовным для новых запросов.Однако текущие запросы могут и не получаться, и это может раздражать клиентов во время загрузки очень больших файлов.

Мы можем настроить перехваты Pre-Stop жизненного цикла контейнера в нашей спецификации развертывания, чтобы ввести паузу перед отправкой завершения работысигналы к приложению через его PID.Это помогает предотвратить любой новый трафик, идущий к модулям, которые были установлены на Завершение.Есть ли способ приостановить процесс завершения работы приложения до тех пор, пока все текущие запросы не будут выполнены (это может занять десятки минут)?

Вот что мы попробовали из приложения Spring Boot:

  • Реализация прослушивателя отключения, который перехватывает ContextCloseEvents;к сожалению, мы не можем надежно получить список активных запросов.Любые метрики привода, которые могли быть полезны, недоступны на данном этапе процесса выключения.

  • Подсчет активных сеансов путем реализации HttpSessionListener и переопределения sessionCreated/Destroy методов для обновления счетчика.Это терпит неудачу, потому что методы не вызываются в отдельном потоке, поэтому всегда сообщайте одно и то же значение в слушателе завершения работы.

Любая другая стратегия, которую мы должны попробовать?Из самого приложения, или из контейнера, или напрямую через дескрипторы ресурсов Kubernetes?Советы / справка / указатели были бы весьма признательны.

Редактировать: мы управляем кластером, поэтому мы пытаемся уменьшить простои служб только для подключенных в данный момент клиентов во время управляемого обновления нашего развертывания через модифицированный модуль.spec

Ответы [ 2 ]

4 голосов
/ 18 мая 2019

Вы можете увеличить terminationGracePeriodSeconds, по умолчанию 30 секунд.Но, к сожалению, ничто не мешает администратору кластера принудительно удалить ваш модуль, и есть множество причин, по которым весь узел может исчезнуть.

0 голосов
/ 21 мая 2019

Мы сделали комбинацию из вышеперечисленного, чтобы решить нашу проблему.

  • увеличил значение TerminationGracePeriodSeconds до абсолютного максимума, который мы ожидаем увидеть в производстве
  • добавлен livenessProbe для предотвращения слишком быстрой маршрутизации Traefik на наш модуль
  • ввел предварительную остановкуловушка, вставляющая паузу и вызывающая скрипт мониторинга:
    1. Отслеживаемый netstat для УСТАНОВЛЕННЫХ подключений к нашему процессу (pid 1) с внешним адресом нашего кластера службы Traefik
    2. отправил TERM в pid 1

Обратите внимание, что поскольку мы посылаем TERM в pid 1 из сценария мониторинга, в этот момент модуль pod завершается, а terminationGracePeriodSeconds никогда не попадает (это делается в качестве меры предосторожности)

Вот сценарий:

#!/bin/sh

while [ "$(/bin/netstat -ap 2>/dev/null | /bin/grep http-alt.*ESTABLISHED.*1/java | grep -c traefik-ingress-service)" -gt 0 ]
do
  sleep 1
done

kill -TERM 1

Вот новая спецификация модуля:

containers:
  - env:
    - name: spring_profiles_active
      value: dev
    image: container.registry.host/project/app:@@version@@
    imagePullPolicy: Always
    lifecycle:
      preStop:
        exec:
          command:
          - /bin/sh
          - -c
          - sleep 5 && /monitoring.sh
    livenessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 60
      periodSeconds: 20
      timeoutSeconds: 3
    name: app
    ports:
    - containerPort: 8080
    readinessProbe:
      httpGet:
        path: /actuator/health
        port: 8080
      initialDelaySeconds: 60
    resources:
      limits:
        cpu: 2
        memory: 2Gi
      requests:
        cpu: 2
        memory: 2Gi
  imagePullSecrets:
  - name: app-secret
  serviceAccountName: vault-auth
  terminationGracePeriodSeconds: 86400
...