Приложение Self healing Spring: как перезагрузить компонент Spring в случае сбоя?

#java #spring #spring-mvc

#java #весна #весна-mvc #spring-mvc

Вопрос:

У меня есть приложение rest, в котором класс RootConfiguration определен как:

 public class RootContextConfiguration implements AsyncConfigurer,
        SchedulingConfigurer
  

Класс RootContextConfiguation содержит несколько компонентов кода, таких как:

 @Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public MyCustomBean myCustomBean() {
    MyCustomBean myCustomBean = new MyCustomBean();
    return myCustomBean;
}
  

RootContextConfiguration зарегистрирован в моем классе FrameworkBootstrap, который определяется как:

 public class FrameworkBootstrap implements WebApplicationInitializer
  

Способ, которым я регистрирую RootConfiguration:

 @Override
    public void onStartup(ServletContext container) throws ServletException {

// AnnotationConfigWebApplicationContext extends the AbstractRefreshableWebApplicationContext abstract class
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(RootContextConfiguration.class);
        container.addListener(new ContextLoaderListener(rootContext));
  

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

Есть ли способ автоматического восстановления после сбоя компонента?

Я использую Spring 4.2.3.RELEASE.

В принципе, мне интересно, если компонент имеет область видимости в качестве прототипа, но каким-то образом он выходит из строя в ApplicationContext, могу ли я перезагрузить компонент, который выходит из строя автоматически? Другими словами, это был бы какой-либо метод, который я мог бы использовать для автоматической перезагрузки ApplicationContext в случае сбоя?

Я хотел бы иметь приложение self healing. Возможно ли это?

Заранее благодарю вас,

C.

Комментарии:

1. дайте определение «сбоя компонента». Обычно Spring не поможет воссоздать компонент в плохом состоянии. Однако, если у вас есть способ определить, что компонент находится в плохом состоянии, почему бы не создать прокси-сервер в качестве компонента, который будет создан spring, и в этом прокси вы прозрачно создаете obj для делегирования вызовов?

2. Ну, в последний раз сбой компонента произошел из-за ограничения JVM из-за большей структуры данных CopyuOnWriteArrayList. Если есть способ убедиться, что компонент действителен, или проверить его до его использования, это было бы здорово. Возможно, лучше использовать фабрику прокси-компонентов, но мне нужно посмотреть несколько примеров. Я подумал, что, используя прототип области видимости, у меня был бы более безопасный компонент, который был бы просто синглтоном для списка.

3. Но, я думаю, следуя документации, что переход на фабрику компонентов может быть похож на выполнение приложений, как в старые времена. Я предполагаю, что основная цель заключается в том, как вы перезагружаете ApplicationContext, в данном случае класс RootContextConfiguration в случае возникновения исключения во время выполнения.

4. бессмысленно обсуждать, если вы четко сообщите нам, что вы подразумеваете под «разбитым компонентом», и как мы должны отличать «разбитый компонент» от обычных

Ответ №1:

Ваш вопрос не имеет смысла. Может быть, почитайте об исключениях. Мы, разработчики, не говорим о «сбое», просто генерируются исключения. JVM никогда не должна «вылетать». Экземпляры класса также не работают, они просто генерируют исключения. Весной исключение, если оно не перехвачено, может быть передано обратно на контроллер с @ControllerAdvice аннотацией сверху, и соответствующее исключение может быть помещено в один из его методов : @ExceptionHandler(YourException.class) public String yourMethod() . Если бы вы знали, что ваш класс выдал определенное исключение, вы могли бы перехватить его там, а затем делать все, что хотите, возвращать страницу с ошибкой в распознаватель представлений или создавать новый экземпляр и передавать его куда угодно.

 @ControllerAdvice
public class ErrorHandler {

    @ExceptionHandler(DataAccessException.class)
    public String showDatabaseErrorPage()
    {
        return "dataBaseErrorPage";
    }
}
  

В общем, если вы хотите сделать свое приложение надежным, не должно быть возможности иметь компоненты в состоянии «сбой», как вы говорите. Приложение должно показать вам, что не так, а не просто сбой.

Редактировать Я думаю, что для ответа на этот вопрос просто недостаточно информации, но я сделаю все возможное. Во-первых, ConcurrentHashMap должен быть доступен только одному потоку. Убедитесь, что это так, это может быть ваша ошибка. Может быть, именно эта библиотека, о которой вы говорите, имеет эту карту, и вы не предполагаете использовать эту библиотеку более чем в 1 потоке, и вы, я понятия не имею.

Теперь для перезапуска этого «компонента». Если ваше приложение не имеет состояния, за исключением любых сеансовых компонентов, то вы можете использовать HttpSession.invalidate() его в своем @ControllerAdvice контроллере, я полагаю (хотя я никогда не пробовал). Ваше приложение должно быть без состояния, за исключением сеансовых компонентов. Любое другое состояние должно храниться в базе данных, а не в самом веб-приложении. Если вы сделали это, единственное, что вам нужно сделать, это завершить сеанс, поскольку сеансовые компоненты могут быть единственным компонентом, который может стать «поврежденным», поскольку это единственный компонент, в котором находится состояние.

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

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

Комментарии:

1. Приложение не сбой, я транспортная обработка исключений во всем и у меня есть обработчик исключений, а также: @RestEndpointAdvice открытый класс RestExceptionHandler { @ExceptionHandler(ConstraintViolationException.class) публичное ResponseEntity<ErrorResponse> ручка(ConstraintViolationException е) { ErrorResponse ошибки = новый ErrorResponse(); для (ConstraintViolation<?> нарушение : электронный.getConstraintViolations()) { ошибка ErrorItem = новый ErrorItem(); ошибка.setCode(нарушение.getMessageTemplate()); ошибка.то setmessage(нарушение.метод GetMessage()); ошибок.addError («ошибка»); } …

2. Я также защищаю конечные точки rest и все службы. К сожалению, иногда у вас может быть сторонняя библиотека, такая как ANTLR, для создания некоторого исключения RuntimeException, хотя мы стараемся получать их в журналах и больше защищать систему.

3. Но бывают случаи, подобные проблеме с JVM, вот что у меня было в прошлый раз: # # Среда выполнения Java обнаружила фатальную ошибку: # # SIGILL (0x4) на pc = 0x00007f8159238120, pid = 2477, tid = 0x00007f8048fa4700 # # Версия JRE: Java (TM) SE RuntimeСреда (8.0_101-b13) (сборка 1.8.0_101-b13)

4. Зарегистрируйтесь для сопоставления памяти: RAX={method} {0x00007f816cbc87c8} ‘putIfAbsent’ ‘(Ljava / lang / Object;Ljava / lang /Object;) Ljava/lang/Object;’ в ‘java/util/concurrent/ConcurrentHashMap’ RBX={метод} {0x00007f816cbc87c8} ‘putIfAbsent’ ‘(Ljava / lang/Object;Ljava/lang/Object;) Ljava/lang/Object;’ в ‘java/util/concurrent/ConcurrentHashMap’

5. Ваш самый последний комментарий демонстрирует, что вы еще не понимаете концепцию исключения. «Сбой» ничего не значит ни для меня, ни для кого-либо, кроме вас. Я не знаю, что это значит, я не знаю, что это значит, когда вы говорите, что «часть» вашего приложения «разбилась». Что такое кусок? Что такое сбой? Почему вы не можете просто перехватить исключение. Какая-то ConcurrentHashMap постоянно выдает исключение? Почему вы опубликовали все эти материалы, которые мне ничего не говорят во многих разных комментариях? Зачем задавать этот вопрос в SO? Что такое сбой? Что такое кусок? Что такое единорог? Может быть, вам следует спросить философа.