【问题标题】:Increase request timeout for a thread in CFML增加 CFML 中线程的请求超时
【发布时间】:2008-12-23 21:42:14
【问题描述】:

我有一个 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>

如您所见,我已尝试将&lt;cfsetting requestTimeout=240 /&gt; 添加到线程顶部以尝试使其寿命更长...没有骰子。当我看到the CFThread tag has a timeout parameter 时,我也有点兴奋,但后来意识到它只适用于加入线程(action=join)。

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

如果有人对如何使这些线程寿命更长有任何想法,我将不胜感激。

【问题讨论】:

  • 你怎么知道线程超时了?我对 Enterprise 不是特别熟悉,但在我的 Standard 框中,抛出的线程似乎没有超时。
  • 我通过 Application.cfc 的 onError() 方法收到错误电子邮件,该方法在线程超时时调用。此外,托管服务提供商告诉我错误日志中显示了相同的消息。

标签: multithreading coldfusion timeout


【解决方案1】:

我们在服务器上使用 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 秒。不幸的是,我的数据库结构和代码还没有达到那个水平。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • Isaac,每个 PDF 都在其自己的线程中生成,该线程与页面请求并行运行。它们的数量会导致一些排队,但我对此无能为力。
    • 是的,诚然,但这似乎是共享主机趋于成功的一种方式。
    【解决方案3】:

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

    根据livedocs,ColdFusion 8 为CFDocument 标签添加了localUrl 属性,表示图像文件位于同一物理机上,应作为本地文件包含在内,而不是发出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>
    

    【讨论】:

      【解决方案4】:

      如果有人发现这篇文章并且他们在即使是简单的 pdf 文件时遇到问题,例如 &lt;cfdocument format="pdf"&gt;Hello world&lt;/cfdocument&gt;(可忽略的内容,没有图像)也需要几分钟才能呈现,请检查您的

      Windows\system32\drivers\etc\hosts

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

      127.0.0.1 localhost
      

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

      【讨论】:

        猜你喜欢
        • 2017-04-29
        • 1970-01-01
        • 2013-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-23
        相关资源
        最近更新 更多