Когда контейнер сервлета прервет мой поток?

#java #servlets

#java #сервлеты

Вопрос:

Я пишу сервлет, который выполняется в контейнере Java servlet (например, JBoss, Jetty, Tomcat, GlassFish).

По каким причинам контейнер сервлета прерывает поток, выполняющий мой обработчик HTTP-запроса? Будет ли это делать только при завершении работы? Будет ли это делать, когда клиент не отвечает?

Это стандартизировано или любой контейнер может делать то, что он хочет?

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

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

1. Чтобы избежать двусмысленности, когда вы сказали «поток», вы на самом деле имеете в виду «HTTP-запрос»?

2. Ну, технически это прервет мой поток, и это произойдет, когда поток выполнит мой HTTP-запрос. Так что я не уверен, как это написать. Перефразировал это, надеюсь, это лучше.

3. Сценарии сильно отличаются, если вы создаете потоки самостоятельно. Итак, вам нужно более четко понимать, какой именно поток вы имеете в виду, и как он был создан, и является ли это потоком демона или нет, и так далее.

4. @BalusC, извините. Нет, я никогда не создаю собственный поток. Я уточню это в вопросе. Я предполагаю, что если я создаю поток, нет никаких причин, по которым он будет вызывать прерывание по этому поводу (как он узнает, что он существует?).

5. Итак, в конце концов, вы на самом деле имеете в виду «HTTP-запрос»? (который сам по себе обслуживается в одном потоке, который управляется самим контейнером)

Ответ №1:

По каким причинам контейнер сервлета прерывает поток, выполняющий мой обработчик HTTP-запроса?

Это зависит от самого контейнера. Это действительно не стандартизировано в спецификации сервлета.

Будет ли это делать только при завершении работы?

Кажется, одна из самых очевидных причин. Локальные тесты показали мне, что, по крайней мере, Tomcat 7.0.22 и Glassfish 3.1.1 немедленно прервут всю обработку сервлета, не позволяя им продолжить выполнение своей задачи. В этот момент никаких исключений не будет.

Будет ли это делать, когда клиент не отвечает?

Только тогда, когда заголовки запроса получены не полностью. Для подключения к сокетам существует тайм-аут, зависящий от контейнера, который обычно составляет 60 секунд. Но если заголовки запроса получены не полностью, то ваш метод сервлета все равно не будет введен. Только если заголовки запроса будут получены полностью, тогда будет введен ваш метод сервлета.

Затем, внутри метода сервлета; если клиент предоставил тело запроса (например, POST ), и код вашего сервлета начнет считывать тело запроса, например request.getParameter() , с помощью или request.getInputStream() , тогда он будет выдан IOException , когда клиент прервал отправку тела запроса в этот момент. С другой стороны, когда вы записываете ответ (и сбрасываете / фиксируете его), тогда также IOException будет выдан ответ, когда клиент прервет соединение в этот момент. При необходимости вы можете поместить его в a try-catch , но вы не можете сделать с ним ничего, кроме простого ведения журнала. Полезность этих регистраций весьма сомнительна и, скорее всего, только загромождает журналы вашего сервера.

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

1. Итак, в принципе, я могу игнорировать InterruptedException код сервлета, поскольку этого никогда не должно быть?

2. ДА. Более того, вы можете перехватить его, только если вы сами создаете потоки и управляете ими.

3. Я могу перехватить его, например, с process.waitFor() помощью которого он его выдает.

4. Это просто поток, который вы создали сами, и поэтому вам приходится управлять им самостоятельно. Это довольно плохая идея, хотя для веб-приложения Java EE, работающего всю жизнь. Кроме того, каждое Runtime#exec() ваше действие создаст новый контекст времени выполнения JVM, который выделяет столько памяти, сколько в данный момент работает JVM веб-сервера. Будьте предупреждены о проблемах с нехваткой памяти, когда несколько посетителей делают это одновременно… Я бы переосмыслил этот подход. Перенесите его на Java или используйте JNI / JNA или, возможно, RMI.

5. (да, но я создал этот поток неявно) ЧТО ?! Нет ли какого-либо переносимого разумного Java-способа выполнить другой процесс? Является ли Java одним из тех эгоистичных созданий, которые вы либо принимаете полностью, либо никогда не используете? Я не могу переносить сторонние двоичные файлы на Java, вы знаете… Разве он не может использовать vfork для выполнения процесса? (Спасибо за очень важный совет)