增加CFML中线程的请求超时

时间:2008-12-23 21:42:14

标签: multithreading coldfusion timeout

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

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

流程是这样的:

  1. 运行页面以生成PDF。
  2. 运行查询以确定需要生成哪些PDF,并且循环会针对需要生成的每个PDF触发应用程序范围的UDF调用。
  3. UDF查找给定项目的信息,然后为PDF生成工作创建一个线程,防止生成减慢页面速度。
  4. 线程只使用CFDocument创建PDF并将其保存到磁盘,然后终止。
  5. 线程不会重新加入,没有任何东西在等待它们中的任何一个完成。进行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 />以尝试让它活得更久......没有骰子。当我看到the CFThread tag has a timeout parameter时,我也有点兴奋,但后来意识到它只适用于加入线程(action = join)。

    在ColdFusion Administrator中更改默认超时不是一个选项,因为这是一个共享主机。

    如果有人对如何让这些线程延长寿命有任何想法,我会非常感激。

4 个答案:

答案 0 :(得分: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秒。不幸的是,我的数据库结构和代码尚未达到该级别。

答案 1 :(得分:2)

我认为有一种方法可以让您在无法访问cf admin的共享主机上延长线程的使用寿命。我认为cf admin限制总是会在激活时覆盖cfsetting requesttimeout值,所以我认为你的手在这方面非常紧密。

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

答案 2 :(得分:1)

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

根据livedocs,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>

答案 3 :(得分:0)

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

Windows \ system32 \ drivers \ etc \ hosts

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

127.0.0.1 localhost

我有一台服务器正常运行,然后突然pdf超时,直到我将CF管理员超时设置为5分钟(?!?!?!)。一些更新(由我不知道是谁,可能是一些网络安全管理员/监控人员)将上述文件修改为其他一些内部网IP和DNS服务器名称。我将其更改回来,pdfs在正常时间响应中恢复渲染。