我有一个Web应用程序,在Windows / IIS服务器上使用ColdFusion 8批量生成数百个PDF。
这个过程在我的开发和登台服务器上运行良好,但当然客户端很便宜并且只支付共享主机,这不如我的开发/暂存盒那么快。因此,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 />
以尝试让它活得更久......没有骰子。当我看到the CFThread tag has a timeout parameter时,我也有点兴奋,但后来意识到它只适用于加入线程(action = join)。
在ColdFusion Administrator中更改默认超时不是一个选项,因为这是一个共享主机。
如果有人对如何让这些线程延长寿命有任何想法,我会非常感激。
答案 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在正常时间响应中恢复渲染。