#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? Что такое сбой? Что такое кусок? Что такое единорог? Может быть, вам следует спросить философа.