首先,我在 CF Admin 中将超时请求(秒(设置为20
。
然后我运行一个带有类似 while(true);
的行的 cfm
该页面将运行超过 20 秒,并且在我撰写本文时线程仍然处于活动状态。
下面是使用服务器监视器拍摄的快照
Thread jrpp-3 request type - TEMPLATE REQUEST
*Template Path - D:ProjectsinfiniteLoop.cfm
*Request Parameters - {}
*Request Method - GET
*Client IP address - 127.0.0.1
*Thread elapsed time - 322659 milliseconds
这正常吗?? 这是 CF9.0.1.,开发人员版本。多实例设置,使用 JRun。
停止无限循环的唯一方法是重新启动 CF。
ColdFuison 中的请求超时不会按照您预期的方式运行。他们呈现的方式,你会想象有一个看门狗来检查你的请求已经运行了多长时间,并在请求超时时或之后不久杀死它。实际发生的是,只有当运行某些标记时,CF 才会检查请求的运行时间是否超过设置的限制。 <cfoutput>
是它检查的标签之一,这就是为什么您经常看到指向 cfoutput 的超时超出消息,即使您知道执行时间不会很长。
<cfsetting requesttimeout="5" enableCFoutputOnly="no" />
<!--- Looping with a condition <cfloop blamed --->
<cfset request.counter=0 />
<cfloop condition="true">
<cfset sleep(1000) />
<cfset request.counter=request.counter+1>
<cflog file="timeout" text="#request.counter#">
<cfif request.counter GT 8>
<cfbreak>
</cfif>
</cfloop>
<!--- Looping with an index, times out, naming CFLOOP as the offending tag --->
<cfloop index="foo" from="1" to="8">
<cfset sleep(1000) />
</cfloop>
<!--- Looping with an index, times out, naming CFOUTPUT as the offending tag --->
<cfloop index="foo" from="1" to="8">
<cfset sleep(1000) />
<cfoutput>Hello</cfoutput>
</cfloop>
<!--- Same loop, but in script. No timeout warning at all --->
<cfscript>
for(foo=1;foo<=8;foo++){
sleep(1000);
}
</cfscript>
<!--- Same loop, now with WriteOutput() called. Still no timeout --->
<cfscript>
for(foo=1;foo<=8;foo++){
sleep(1000);
writeoutput("tick...");
}
</cfscript>
上面的代码显示了请求超时的一些奇怪行为。正如 Mark Kruger 指出的那样,对外部资源的任何调用都意味着不检查超时,我猜只是执行你自己的逻辑的大块脚本也不会被检查,留下下一个输出语句被指责。
如果您需要跟踪代码滞后的位置以及超时消息指向错误的位置,我会使用日志记录或 jstack 在长时间运行的代码运行时从服务器获取堆栈跟踪。每隔几秒钟获取一些堆栈跟踪,然后通过 Samurai 运行日志文件以查找代码正在执行的操作。
不幸的是,当您知道 ColdFusion 中请求超时检查的约束时,您描述的是预期行为。 (当然,这不应该是预期的行为。
Charlie Arehart有一篇关于超时问题的长博客文章。 其中一个部分的标题是"CF 在下一个操作开始时检查时间,但遗憾的是只在某些标签上"。 不幸的是,cfscript
不是其中之一,并且不会使用纯脚本代码检查超时。 但是,触发超时检查的标记之一是cfoutput
并且有了这些知识,就可以使基于脚本的代码尊重请求超时。 但是,这是一个手动过程,因为您需要自己决定应该在哪里检查超时。
<cffunction name="cf_checkRequestTimeout" access="public" output="false" returntype="void" hint="Force CF to check if the request has timed out.">
<!--- CF checks Request timeout on cfoutput tag use. --->
<cfoutput></cfoutput>
</cffunction>
<cfscript>
for(foo=1;foo<=61;foo++){
sleep(1000);
cf_checkRequestTimeout();
}
</cfscript>
生成的错误将归咎于第 4 行,这是误导性的,但堆栈跟踪将显示该函数是从第 11 行调用的,然后允许您知道哪位代码超时。 显然,该知识的粒度基于检查超时的频率。
cf_checkRequestTimeout
(不是checkRequestTimeout
,因为这是一个未记录的内部 CF 函数(也可以在 cfscript 之外调用,因此,例如,如果您有一个cfquery
,您认为会导致超时问题,那么您可以将cf_checkRequestTimeout
调用放在cfquery
之后,并将超时错误放在应有的位置,而不是在代码执行中进一步向下。
我发现和亨利一样。 这是我的测试代码:
Before thread<br />
<cfthread action="run" name="t1">
<cfloop condition="true">
<cfparam name="count" default="0">
<cfset sleep(3000)>
<cflog file="cfthreadTest" text="Log entry #++count#">
</cfloop>
</cfthread>
After thread<br />
我的请求超时在 CFAdmin 中设置为 20 秒,此线程现在已经运行了 15 分钟。 也就是说,线程不是"请求",所以我不确定我是否希望它遵守请求超时。 我找不到任何文档表明它应该尊重请求超时。 可是。。。有某种杀死线程的方法将是"方便的"。
我想这只是上下文中的"答案",我认为您的期望不正确,因为您希望它尊重请求超时。