2008-12-23 4 views
1

У меня есть веб-приложение, которое генерирует сотни PDF-файлов в пакетном режиме, используя ColdFusion 8 на сервере Windows/IIS.Увеличьте время ожидания запроса для потока в CFML

Процесс отлично работает на моих серверах разработки и промежуточного уровня, но, конечно, клиент дешев и платит только за общий хостинг, который не так быстро, как у моих dev/промежуточных ящиков. В результате потоки генерации PDF синхронизируются.

Поток что-то вроде этого:

  1. Страница выполняется для создания PDF-файлов.
  2. Выполняется запрос для определения того, какие PDF-файлы должны быть сгенерированы, а цикл запускает вызов UDF с областью приложения для каждого PDF-документа, который необходимо будет сгенерировать.
  3. Этот UDF просматривает информацию для данного элемента, а затем создает поток для генерации PDF, в котором работает, что предотвращает замедление производства.
  4. В потоке просто используется документ CFDocument для создания PDF-файла и сохранения его на диск, а затем завершается.

Нити не присоединяются, и ничто из них не ждет завершения. Страница, на которой заканчиваются вызовы UDF за несколько миллисекунд; это сами потоки, которые выходят из строя.

Вот код ОДС (и создания потока):

<cffunction name="genTearSheet" output="false" returntype="void"> 
    <cfargument name="partId" type="numeric" required="true"/> 
    <!--- saveLocation can be a relative or absolute path ---> 
    <cfargument name="saveLocation" type="string" required="true"/> 
    <cfargument name="overwrite" type="boolean" required="false" default="true" /> 
    <cfset var local = structNew() /> 

    <!--- fix save location if we need to ---> 
    <cfif left(arguments.saveLocation, 1) eq "/"> 
     <cfset arguments.saveLocation = expandPath(arguments.saveLocation) /> 
    </cfif> 

    <!--- get part info ---> 
    <cfif structKeyExists(application, "partGateway")> 
     <cfset local.part = application.partGateway 
     .getByAttributesQuery(partId: arguments.partId)/> 
    <cfelse> 
     <cfset local.part = createObject("component","com.admin.partGateway") 
     .init(application.dsn).getByAttributesQuery(partId: arguments.partId)/> 
    </cfif> 

    <!--- define file name to be saved ---> 
    <cfif right(arguments.saveLocation, 4) neq ".pdf"> 
     <cfif right(arguments.saveLocation, 1) neq "/"> 
      <cfset arguments.saveLocation = arguments.saveLocation & "/" /> 
     </cfif> 
     <cfset arguments.saveLocation = arguments.saveLocation & 
     "ts_#application.udf.sanitizePartNum(local.part.PartNum)#.pdf"/> 
    </cfif> 

    <!--- generate the new PDF in a thread so that page processing can continue ---> 
    <cfthread name="thread-genTearSheet-partid-#arguments.partId#" action="run" 
    filename="#arguments.saveLocation#" part="#local.part#" 
    overwrite="#arguments.overwrite#"> 
     <cfsetting requestTimeOut=240 /> 
     <cftry> 
     <cfoutput> 
     <cfdocument format="PDF" marginbottom="0.75" 
     filename="#attributes.fileName#" overwrite="#attributes.overwrite#"> 
      <cfdocumentitem type="footer"> 
       <center> 
       <font face="Tahoma" color="black" size="7pt"> 
       pdf footer text here 
       </font> 
       </center> 
      </cfdocumentitem> 
      pdf body here 
     </cfdocument> 
     </cfoutput> 
     <cfcatch> 
     <cfset application.udf.errorEmail(application.errorEmail, 
     "Error in threaded PDF save", cfcatch)/> 
     </cfcatch> 
     </cftry> 
    </cfthread> 
</cffunction> 

Как вы можете видеть, я попытался добавить <cfsetting requestTimeout=240 /> к верхней нити, чтобы попытаться сделать это жить дольше. .. нет кости. Я также немного взволновался, когда увидел, что the CFThread tag has a timeout parameter, но затем понял, что он применяется только при соединении потоков (action = join).

Изменение тайм-аута по умолчанию в ColdFusion Administrator не является вариантом, так как это общий хост.

Если у кого-то есть идеи о том, как сделать эти потоки живыми дольше, я бы очень их оценил.

+0

Как вы знаете, что потоки выходят из строя? Я не особенно знаком с Enterprise, но на моих стандартных ящиках заброшенные потоки не кажутся тайм-аутами. –

+0

Я получаю письма с ошибкой через метод onError() приложения.cfc, вызываемый при тайм-ауте потоков. Кроме того, хостинг-провайдер сообщает мне, что те же сообщения отображаются в журнале ошибок. –

ответ

1

Хотя это не отвечает прямо на мой первоначальный вопрос об увеличении таймаута потока, я смог заставить процесс работать (предотвращать таймауты), улучшая время генерации PDF.

Согласно livedocs, ColdFusion 8 добавлен атрибут к CFDocument тег, который указывает, что файлы изображений расположены на одной и той же физической машине, и должны быть включены в локальные файлы вместо того, чтобы запрос HTTP для них localUrl.

Изменение моего CFDocument приведенного ниже кода заставило процесс работать достаточно быстро, чтобы потоки не выходили из строя.

<cfdocument format="PDF" marginbottom="0.75" 
filename="#attributes.fileName#" overwrite="#attributes.overwrite#" localUrl="yes"> 
    <cfdocumentitem type="footer"> 
     <center> 
     <font face="Tahoma" color="black" size="7pt"> 
      pdf footer text here 
     </font> 
     </center> 
    </cfdocumentitem> 
    pdf body here 
    <img src="images/foo/bar.gif"/> 
</cfdocument> 
-1
+0

Я ... бег ... параллельно ... темы ... –

+0

Я думаю, что -1 суровый. Я указал на этот URL, потому что я не вижу Это строка, которая будет ждать остановки потоков до окончания запроса главной страницы –

+0

(Это был не я, проголосовал за это, я бы не стал тратить на него свой репорт.) Я не хочу, чтобы нити присоединились, потому что нет необходимости. Их следует начинать и забывать. Проблема в том, что они индивидуально отключаются. –

2

Я не думаю, что есть способ, чтобы сделать нить жить дольше на виртуальном хостинге, где у вас нет доступа к КФ администратора. Я думаю, что ограничение cf admin всегда переопределяет значение времени ожидания cfsetting, когда оно активировано, поэтому я думаю, что ваши руки в значительной степени связаны с этим фронтом.

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

+0

Isaac, каждый PDF создается в своем потоке, параллельном запросу страницы. Количество из них вызовет некоторую очередность, но я не могу с этим поделать. –

+0

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

3

Мы используем 90-секундный тайм-аут в целом на нашем сервере (набор в администратора CF), но использовать операторы в файлах CFM для переопределения, что установка в случае необходимости. У нас также есть журнал регистрации любого запроса, который длится 30 секунд или более, поэтому мы знаем, какие из них нужно оптимизировать и/или нуждаться в переопределении времени ожидания запроса (хотя запрошенный тайм-аут будет очевидным по другим причинам, его приятно иметь список ваших самые медленные транзакции в C: \ ColdFusion8 \ logs \ server.log).

Например, на вершине CFM, которая запускается в качестве ночной задачи я вижу:

<cfsetting enablecfoutputonly="Yes" showdebugoutput="No" requesttimeout="80000"> 

Я могу вам сказать, что прошлой ночью он бежал потребовалось 34,313 секунд. Очевидно, комната для улучшения этого процесса, но он заканчивается за несколько часов до начала рабочего дня. Если этот параметр requesttimeout не был установлен в CFM-файле, то задание будет определенно тайм-аутом на отметке 90 секунд.

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

0

В случае, если кто находит этот пост, и они возникают проблемы, где даже простой PDFs, например, <cfdocument format="pdf">Hello world</cfdocument> (незначительное содержания, никаких изображений) не принимают минуты рендеринга, проверьте

Windows \ system32 \ Drivers \ Etc \ хозяева

файловый сервер и убедитесь, что он указывает на себя

127.0.0.1 localhost 

у меня был сервер работает нормально, а потом вдруг ПРВ были таймаут, пока я не установить тайм-аут CF администратора до 5 минут (?!?! ?!). Некоторое обновление (сделанное я не знаю, кто, возможно, какой-то администратор сети/монитор сети), модифицировал вышеуказанный файл на другой IP-адрес интрасети и имя DNS-сервера. Я изменил его, и PDF-файлы возобновили рендеринг в обычных ответах времени.

Смежные вопросы