Увеличьте время ожидания запроса для потока в CFML - PullRequest
1 голос
/ 24 декабря 2008

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

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

Поток примерно такой:

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

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

Вот код для 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 /> в начало потока, чтобы попытаться заставить его жить дольше ... без кубиков. Я также был немного взволнован, когда увидел, что тег CFThread имеет параметр времени ожидания , но потом понял, что он применяется только при присоединении к потокам (action = join).

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

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

Ответы [ 4 ]

3 голосов
/ 24 февраля 2009

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

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

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

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

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

2 голосов
/ 31 декабря 2008

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

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

1 голос
/ 09 января 2009

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

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

Изменение моего 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>
0 голосов
/ 11 января 2017

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

Windows \ system32 \ drivers \ etc \ hosts

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

127.0.0.1 localhost

У меня был сервер, работающий нормально, а затем внезапно истекло время ожидания pdf, пока я не установил таймаут CF Admin на 5 минут (?!?!?!). Некоторое обновление (выполненное не знаю, кто, возможно, администратором или наблюдателем по сетевой безопасности) изменило указанный выше файл для другого IP-адреса интрасети и имени DNS-сервера. Я изменил его обратно, и pdfs возобновил рендеринг в обычном времени ответов.

...