it-swarm.com.ru

Тайм-аут запроса Tomcat

В моем веб-приложении есть несколько запросов, которые длятся дольше 20 секунд. Но в некоторых ситуациях код может привести к бесконечному циклу или чему-то подобному, что замедляет работу сервера.

Я хочу поставить тайм-аут запроса на 60 секунд на стороне сервера. Это реализовано в Tomcat?

Спасибо, Горатью

41
Horatiu Jeflea

В Tomcat 7 вы можете добавить StuckThreadDetectionValve , который позволит вам идентифицировать "застрявшие" потоки. Вы можете настроить Valve в элементе Context приложений, в которых вы хотите обнаружить:

<Context ...>
  ...
  <Valve 
    className="org.Apache.catalina.valves.StuckThreadDetectionValve"
    threshold="60" />
  ...
</Context>

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

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

44
beny23

Если вы пытаетесь помешать выполнению запроса слишком долго, то установка таймаута в Tomcat вам не поможет. Как говорит Крис, вы можете установить значение глобального таймаута для Tomcat. Но, из Соединитель Apache Tomcat - универсальные тайм-ауты HowTo см. Раздел "Тайм-аут ответа":

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

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

Если JK прерывает ожидание ответа, так как истекло время ожидания ответа, нет способа остановить обработку на бэкэнде. Несмотря на то, что вы освобождаете ресурсы обработки на своем веб-сервере, запрос будет продолжать выполняться на бэкэнде - без возможности отправить результат после истечения времени ожидания ответа.

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

22
Matthew Farwell

Вы можете установить время по умолчанию в server.xml

<Connector URIEncoding="UTF-8" 
    acceptCount="100" 
    connectionTimeout="20000" 
    disableUploadTimeout="true" 
    enableLookups="false" 
    maxHttpHeaderSize="8192" 
    maxSpareThreads="75" 
    maxThreads="150" 
    minSpareThreads="25" 
    port="7777" 
    redirectPort="8443"/>
11
Chris

В этой статье рассказывается об установке тайм-аутов на уровне сервера. http://www.coderanch.com/t/364207/Servlets/Java/Servlet-Timeout-two-ways

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

1
thcricketfan

Для тех, кому не нравится ни одно из вышеперечисленных решений, как я, вы можете просто реализовать таймер самостоятельно и остановить выполнение запроса, выдав исключение времени выполнения. Что-то вроде ниже:

                  try 
                 {
                     timer.schedule(new TimerTask() {
                       @Override
                       public void run() {
                         timer.cancel();
                       }
                     }, /* specify time of the requst */ 1000);
                 }
                 catch(Exception e)
                 {
                   throw new RuntimeException("the request is taking longer than usual");
                 }

или предпочтительно используйте Java guava timeLimiter здесь

0
george