1

我有一个 Web 应用程序,它在 Windows/IIS 服务器上使用 ColdFusion 8 批量生成数百个 PDF。

该过程在我的开发和登台服务器上运行良好,但当然客户端很便宜并且只为共享主机付费,这不如我的开发/登台盒快。因此,PDF 生成线程超时。

流程是这样的:

  1. 运行页面以生成 PDF。
  2. 运行查询以确定需要生成哪些 PDF,然后循环为需要生成的每个 PDF 触发应用程序范围的 UDF 调用。
  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

4 回答 4

3

我们在服务器上使用 90 秒的总体超时(在 CF 管理员中设置),但在需要时使用 CFM 文件中的语句覆盖该设置。我们还让服务器记录任何持续 30 秒或更长时间的请求,以便我们知道哪些请求需要优化和/或需要 requesttimeout 覆盖(尽管由于其他原因超时请求很明显,很高兴有一个您的列表C:\ColdFusion8\logs\server.log 中最慢的事务)。

例如,在作为夜间任务运行的 CFM 顶部,我看到:

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

我可以告诉你,它在昨晚运行时花了 34,313 秒才能完成。显然还有改进这个过程的空间,但它在办公日开始前几个小时就完成了。如果在 CFM 文件中未设置该 requesttimeout 参数,则该作业肯定会在 90 秒标记处超时。

在我们有更长的任务覆盖该设置之前,我必须从更高的请求超时开始,并在我们收紧工作时观察失败并重新运行作业。理想情况下,如果拥有良好的硬件、代码和良好的数据库结构,我会继续将我的 CF 管理员超时时间缩短到 CF8 默认的 30 秒。不幸的是,我的数据库结构和代码还没有达到那个水平。

于 2009-02-23T23:25:43.037 回答
2

我认为没有办法让线程在您无权访问 cf 管理员的共享主机上存活更长时间。我认为 cf 管理员限制在激活时总是会覆盖 cfsetting requesttimeout 值,所以我认为您的双手几乎都在这方面受到束缚。

我的建议是将策略从在当前页面中创建所有 PDF 更改为对需要创建的每个 PDF 发起另一个请求。不优雅的不显示 iframe 可能是最简单的解决方案。您可以简单地为需要生成的每个 PDF 输出一个 iframe,这样它就永远不会遇到超时问题,因为每个单独的 PDF 都应该在主机设置的时间限制内生成。

于 2008-12-31T02:22:49.323 回答
1

虽然这并不能直接回答我原来增加线程超时的问题,但我已经能够通过改进 PDF 生成时间来使进程正常工作(防止超时)。

根据livedocs,ColdFusion 8localUrl在标签中添加了一个属性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>
于 2009-01-09T15:06:35.500 回答
0

如果有人发现这篇文章并且他们遇到了即使是简单的 pdf 文件(例如<cfdocument format="pdf">Hello world</cfdocument>(可忽略的内容,没有图像)也需要花费几分钟来渲染的麻烦),请检查您的

Windows\system32\drivers\etc\hosts

服务器文件并确保它指向自身

127.0.0.1 localhost

I had a server functioning normally and then suddenly pdfs were timing out until I set the CF Admin timeout to 5 minutes (?!?!?!). Some update (done by I don't know who, probably some network security admin/monitor person) had modified the above file to some other intranet IP and the DNS server name. I changed it back and pdfs resumed rendering in normal time responses.

于 2017-01-10T23:07:11.987 回答