Запланированная задача останавливается по необъяснимым причинам.Есть ли ошибка в запланированной задаче Spring? ?

Java

Здравствуйте~ С Новым годом, читатели! Вот маленький черный брат внизу желает всем нового года, а я желаю вам всем процветающего и жаркого дня.

Эта ошибка

Во время праздника Весны Сяо Хэй ехал домой на скоростном поезде и вдруг подумал о производственной проблеме. Это был первый год работы Сяо Хэя.Во время празднования Национального дня в том же году Сяо Хэй попросился в отпуск за день до начала, чтобы пойти домой, чтобы получить паспорт. В то время я только начал руководить производственной системой, поэтому немного беспокоился о том, чтобы проситься в отпуск по рабочим дням.проблемаУвидев, что маленького черного брата нет, он тихонько подошел к двери.

Эй, чем больше ты боишься правды, тем больше ты будешь приходить.

Когда высокоскоростная железная дорога была на полпути, коллеги сообщили, что система не может получить последнюю информацию о текущей воде (информация о текущей водеSpringЗадачи на время вытягиваются регулярно). Маленький черный брат вздрогнул, он тут же вытащил компьютер и подключилVPN, готовы сесть на производственную машину и проверить состояние системы. Однако всем известно, что сеть высокоскоростных железных дорог очень нестабильна, и подключиться к ней уже давно не удается.VPN, мне пришлось удаленно дать команду коллегам посмотреть системный журнал. Благодаря отзывам коллег в журнале было обнаружено, что запланированная задача по извлечению конвейера не была выполнена.После дальнейшей проверки Сяо Хей обнаружил, что другие запланированные задачи во всей системе также были остановлены. . .

Это действительно странный вопрос, как эта хорошая временная задача может внезапно остановиться?

Я пока не мог придумать решения, поэтому мне пришлось поручить моим коллегам сначала перезапустить приложение. После перезапуска проблема временно решается, запланированная задача перезапускается, а также получается последняя информация о потоке платежей.

Устранение неполадок

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

Через системный журнал был обнаружен проблемный код.

используется здесьПовторить стратегию компенсации, чтобы предотвратить случайный сбой информации о конвейере запросов из-за сетевых проблем. Эта стратегия удобна при случайных сбоях, но если запросы к сервису банковских потоков будут сбоить все время, этот код попадет в бесконечный цикл. Бывало, что в это время были какие-то проблемы с сетью, из-за чего этот запрос все время не давался.

Увеличьте максимальное количество попыток, чтобы исправить ошибку.Bug.

После исправления последняя версия кода была немедленно развернута в рабочей системе, что временно решило проблему.

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

Углубленное расследование

Несмотря на то, что проблема решена, Сяо Хэй все еще сомневается в своем сердце, почему заблокирована задача на время, что повлияет на выполнение других задач на время. Изначально брат Сяо Хэй понимал, что задачи с разными временными рамками должны быть изолированы друг от друга и не влиять друг на друга.Это действительно сложно.Springзадача на времяBug?

Думая об этом, маленький черный брат решил написатьDemo, воспроизведите проблему, а затем изучите исходный код для устранения неполадок.

Запускаем программу, вывод лога такой:

image-20200124160151622

Как видно из журнала,fixDelayMethodПосле выполнения метод уходит в спящий режим до конца сна,cronMethodТолько временные задачи имеют возможность быть выполненными. Кроме того, как видно из вышеизложенного, две вышеуказанные временные задачи являютсяpool-1-thread-1Выполнение потока. Отсюда видно, чтоSpringЗапланированные задачи будут переданы в пул потоков для выполнения.

Сводка знаний: стратегия именования потоков по умолчанию в пуле потоков — pool-%poolNumber-thread-%num.

Если в пуле потоков есть только один рабочий поток, после того, как поток будет заблокирован на долгое время, другие накопленные задачи не смогут быть выполнены.

Так в этом проблема?SpingЗапланированные задачи перестают выполняться? Продолжим расследование.

Зеленая часть бревна на рисунке,ScheduledAnnotationBeanPostProcessorВыводится важное сообщение:

No TaskScheduler/ScheduledExecutorService bean found for scheduled processing

ПроверятьSpringДокументация,SpringВнутренне он будет вызыватьсяTaskSchedulerвыполнить запланированную задачу, в то время как другаяScheduledExecutorServiceзаJDKПредоставляет исполнитель, который выполняет задачи по времени. помни оба

image-20200125140457573

Используя этот журнал, используйте мощные возможности IDEA.Функция поиска по ключевым словам,ТаргетингScheduledAnnotationBeanPostProcessor#finishRegistrationметод.

Этот способ относительно долгий, и все ориентируются на несколько пунктов, отмеченных на рисунке.

SpringПосле запуска он просканирует всеBeanс участием@ScheduledАннотированный метод, а затем инкапсулированный какTaskподклассы помещаются вScheduledTaskRegistrar.

Этот код находится вScheduledAnnotationBeanPostProcessor#processScheduled, если вам интересно, вы можете прочитать это

если в это времяScheduledTaskRegistrarНет запланированной задачи илиScheduledTaskRegistrarсерединаTaskSchedulerне существует,finishRegistrationбудет вызываться несколько разScheduledAnnotationBeanPostProcessor#resolveSchedulerBeanспособ найтиTaskScheduler/ScheduledExecutorService.

Далее получитеBeanпройти черезsetSchedulerвводить вScheduledTaskRegistrarсередина.

Если полученоScheduledExecutorServiceтип, который будет инкапсулирован вtaskSchedulerсередина.

Если он не будет найден в конце, он выведет журнал, который был увиден первым. потомSpirngбудет вScheduledTaskRegistrar#afterPropertiesSetСоздание однопоточного исполнителя запланированных задачScheduledExecutorService, введенный вConcurrentTaskScheduler, затем черезtaskSchedulerВыполнение задач на время.

image-20200125144040781

сдаватьTaskSchedulerВременная задача фактически завершаетсяScheduledExecutorServiceвоплощать в жизнь.

Здесь можно получитьв заключении:

SpringВременная задача фактически проходитJDKкоторый предоставилScheduledExecutorServiceвоплощать в жизнь. По умолчанию Spring создаст один поток.ScheduledExecutorServiceВыполнение задач на время. Таким образом, как только определенная задача синхронизации блокирует поток выполнения на долгое время, это повлияет на другие задачи синхронизации, и поток выполнения не сможет их выполнить.

Конфигурация Spring по умолчанию может быть ямой, когда необходимо выполнить несколько запланированных задач. Мы можем заставить Spring использовать многопоточность для выполнения задач по времени, изменив конфигурацию.

пользовательская конфигурация

Spring может изменить конфигурацию по умолчанию несколькими способами.

XML-конфигурация

пройти черезxmlнастроитьTaskSchedulerПотоки.

<task:annotation-driven  scheduler="myScheduler"/>
<task:scheduler id="myScheduler" pool-size="10"/>

С приведенной выше конфигурацией Spring будет использоватьTaskSchedulerПодклассThreadPoolTaskScheduler, количество внутренних потоковpool-sizeКоличество потоков, количество потоков будет установлено напрямуюScheduledExecutorServiceколичество потоков.

Конфигурация аннотации

В приведенном выше устранении неполадок мы знаем, чтоSpringнайдуTaskScheduler/ScheduledExecutorService, будет использоваться, если он существует. Итак, здесь мы можем сгенерировать эти классыBean.

Вы можете выбрать один из вышеперечисленных способов

Конфигурация весенней загрузки

Вышеуказанные две конфигурации подходят для обычныхSpring, сложнее. в отличиеSpringBootКонфигурация будет очень простой, просто добавьте следующую конфигурацию в файл конфигурации запуска.

spring.task.scheduling.pool.size=10
spring.task.scheduling.thread-name-prefix=task-test

Техническое резюме

Начнем техническое резюме:

  1. SpringПринцип выполнения временной задачи фактически используетJDKавтономныйScheduledExecutorService
  2. SpringПо умолчанию однопоточныйScheduledExecutorService
  3. Однопоточное выполнение задач по времени, если определенная задача по времени выполняется в течение длительного времени, это повлияет на выполнение других задач по времени
  4. Если есть несколько запланированных задач, чтобы обеспечить точность времени выполнения запланированных задач, вы можете изменить конфигурацию по умолчанию, чтобы использовать несколько потоков для выполнения запланированных задач.
  5. Перед лицом случайных сбоев мы можем использовать стратегию компенсации повторных попыток, но не забудьте установить здесь соответствующее максимальное количество повторных попыток.

просто поболтать

Для распространенных фреймворков с открытым исходным кодом мы должны не только освоить их использование, но и ознакомиться с соответствующими конфигурациями и, наконец, понять принципы их внутреннего использования. Если таким образом возникает проблема, мы также можем быстро обнаружить проблему и найти фактическую причину проблемы.

справочная документация

Spring scheduling-task-scheduler

Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: программа для общения, ежедневный толчок галантерейных товаров. Если вам интересен мой рекомендуемый контент, вы также можете подписаться на мой блог:studyidea.cn