Эта проблема
Так что через несколько дней я смог вернуться к своему маленькому проекту Recaps. Я начал с проверки логов и нашел что-то вроде этого:
1
2
3
4
|
2012-03-04T01:52:51+00:00 heroku[web.1]: Idling 2012-03-04T01:52:53+00:00 heroku[web.1]: Stopping process with SIGTERM 2012-03-04T01:53:03+00:00 heroku[web.1]: Error R12 (Exit timeout) -> Process failed to exit within 10 seconds of SIGTERM 2012-03-04T01:53:03+00:00 heroku[web.1]: Stopping process with SIGKILL |
Я не знаю, что вы думаете, но всякий раз, когда я вижу «Ошибка» в моих журналах, я беспокоюсь. Поэтому я решил убрать эту неприятную черту. То, что произошло, не понравилось.
Решение
Это кажется простой проблемой. Я начал с того, что нашел, что это за SIGTERM. Я знал, что это сигнал от Linux, я просто хотел знать, что на самом деле делает Heroku. Поэтому иногда Heroku просто отправляет SIGTERM в ваш процесс, чтобы ему было разрешено корректно завершить работу. Это очень просто.
Как я уже упоминал в своем последнем посте, я решил использовать Jetty вместо Grizzly. Сначала я решил использовать jetty-runner для запуска моего веб-приложения, и оно работало нормально, ресурсы сканировались при запуске сервлета Джерси. Развертывание в Heroku также было простым, и с измененным Procfile приложение запустилось.
Тем не менее приложение не реагировало правильно на SIGTERM, поэтому, не углубляясь в настройку Jetty-Runner, я решил просто использовать встроенный сервер Jetty. Это очень просто, и запуск мастера запускает приложение. Поэтому без дальнейшего рассмотрения я просто развернул измененное приложение в Heroku. Чтобы проверить, появляется ли ошибка снова, после первого запуска я просто перезагрузил heroku и подключился к логам в другом терминале. Но сообщение об ошибке тайм-аута выхода все еще было. Моя ошибка там — я не проверял приложение, будет ли оно правильно работать при использовании мастера. Итак, снова запускается мастер, а затем ctrl + c, чтобы посмотреть, что произойдет (позже я попытался выполнить команду kill -s TERM и получил аналогичный вывод):
01
02
03
04
05
06
07
08
09
10
11
12
|
pbu@pbudesk ~ /recaps $ foreman start 21:57:27 web.1 | started with pid 9603 21:57:27 web.1 | 0 [main] INFO org.eclipse.jetty.server.Server - jetty-8.1.1.v20120215 21:57:27 web.1 | 110 [main] INFO org.eclipse.jetty.webapp.StandardDescriptorProcessor - NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet 21:57:27 web.1 | 132 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - started o.e.j.w.WebAppContext{/, file : /home/pbu/Devel/IdeaProjects/recaps/webmodule/src/main/webapp/ },webmodule /src/main/webapp 21:57:27 web.1 | 133 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - started o.e.j.w.WebAppContext{/, file : /home/pbu/Devel/IdeaProjects/recaps/webmodule/src/main/webapp/ },webmodule /src/main/webapp 21:57:27 web.1 | 183 [main] INFO org.eclipse.jetty.server.AbstractConnector - Started [email protected]:5000 ^CSIGINT received 21:57:57 system | sending SIGTERM to all processes 21:57:57 system | sending SIGTERM to pid 9603 21:57:57 web.1 | process terminated pbu@pbudesk ~ /recaps $ |
Хорошо, поэтому, когда мастер получает SIGINT, он отправляет SIGTERM всем процессам, круто — вероятно, династии Heroku ведут себя одинаково. Тем не менее, это было не изящное завершение работы, но в Jetty есть раздел изящного завершения работы, в котором упоминаются два приятных свойства: gracefulShutdown и stopAtShutdown. Модифицированный класс выглядит так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public class Serve { public static void main(String[] args) throws Exception { int port = Integer.valueOf(System.getenv( "PORT" )); Server jetty = new Server(port); WebAppContext context = new WebAppContext(); context.setContextPath( "/" ); String webapp = "webmodule/src/main/webapp" ; context.setWar(webapp); context.setResourceBase(webapp); jetty.setHandler(context); jetty.setGracefulShutdown( 1000 ); jetty.setStopAtShutdown( true ); jetty.start(); jetty.join(); } } |
Повторный запуск мастера и использование ctrl + c доказывает, что это работает! Большой!
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
pbu@pbudesk ~ /recaps $ foreman start 22:11:47 web.1 | started with pid 9863 22:11:47 web.1 | 0 [main] INFO org.eclipse.jetty.server.Server - jetty-8.1.1.v20120215 22:11:47 web.1 | 110 [main] INFO org.eclipse.jetty.webapp.StandardDescriptorProcessor - NO JSP Support for /, did not find org.apache.jasper.servlet.JspServlet 22:11:47 web.1 | 131 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - started o.e.j.w.WebAppContext{/, file : /home/pbu/Devel/IdeaProjects/recaps/webmodule/src/main/webapp/ },webmodule /src/main/webapp 22:11:47 web.1 | 132 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - started o.e.j.w.WebAppContext{/, file : /home/pbu/Devel/IdeaProjects/recaps/webmodule/src/main/webapp/ },webmodule /src/main/webapp 22:11:48 web.1 | 183 [main] INFO org.eclipse.jetty.server.AbstractConnector - Started [email protected]:5000 ^C22:11:49 web.1 | 1969 [Thread-1] INFO org.eclipse.jetty.server.Server - Graceful shutdown [email protected]:5000 22:11:49 web.1 | 1970 [Thread-1] INFO org.eclipse.jetty.server.Server - Graceful shutdown o.e.j.w.WebAppContext{/, file : /home/pbu/Devel/IdeaProjects/recaps/webmodule/src/main/webapp/ },webmodule /src/main/webapp SIGINT received 22:11:49 system | sending SIGTERM to all processes 22:11:49 system | sending SIGTERM to pid 9863 22:11:50 web.1 | 2982 [Thread-1] INFO org.eclipse.jetty.server.handler.ContextHandler - stopped o.e.j.w.WebAppContext{/, file : /home/pbu/Devel/IdeaProjects/recaps/webmodule/src/main/webapp/ },webmodule /src/main/webapp 22:11:50 web.1 | process terminated pbu@pbudesk ~ /recaps $ So off to deploy it to the cloud! Again, deploy, heroku restart and watch logs... but it doesn't work. |
Другой путь
После первоначального сбоя я попробовал другой подход. Я узнал, что вы можете зарегистрировать хуки отключения — очень простая вещь. Для этого просто зарегистрируйте новый поток с помощью метода Runtime.getRuntime (). AddShutdownHook (Thread):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public class Serve { public static void main(String[] args) throws Exception { Runtime.getRuntime().addShutdownHook( new Thread() { @Override public void run() { System.out.println( "Shutting down by shutdown hook" ); } }); int port = Integer.valueOf(System.getenv( "PORT" )); Server jetty = new Server(port); WebAppContext context = new WebAppContext(); context.setContextPath( "/" ); String webapp = "webmodule/src/main/webapp" ; context.setWar(webapp); context.setResourceBase(webapp); jetty.setHandler(context); jetty.setGracefulShutdown( 1000 ); jetty.setStopAtShutdown( true ); jetty.start(); jetty.join(); } } |
Финальный тест с прорабом доказывает, что он тоже работает, но в очередной раз не работает на Heroku.
На данный момент я понятия не имею, как избавиться от этого тайм-аута. Это не очень важно, я просто хотел проверить, могу ли я как-то на это отреагировать, но безрезультатно. Пока, я думаю, я просто свяжусь с Хероку, может, они помогут. Другим вариантом может быть попытка встроенного Tomcat, но, возможно, позже. На данный момент у меня есть другие дела, такие как проверка Jelastic .