7

首先,我20在 CF Admin 中将 Timeout Requests after (seconds) 设置为。

然后我运行一个 cfm 像这样的一行while(true);

该页面将运行超过 20 秒,并且在我写这篇文章时该线程仍然存在。

下面是使用 Server Monitor 拍摄的快照

Thread  jrpp-3 request type - TEMPLATE REQUEST
*Template Path - D:\Projects\infiniteLoop.cfm
*Request Parameters - {}
*Request Method - GET
*Client IP address - 127.0.0.1
*Thread elapsed time - 322659 milliseconds

这正常吗??这是CF9.0.1.,开发者版。多实例设置,使用 JRun。

停止无限循环的唯一方法是重新启动 CF。

4

3 回答 3

13

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>

上面的代码显示了 requesttimeout 的一些奇怪行为。正如 Mark Kruger 指出的那样,任何对外部资源的调用都意味着不检查超时,我猜只是执行您自己的逻辑的大块脚本也不会被检查,而下一个输出语句将受到指责。

如果您需要跟踪代码滞后的位置并且超时消息指向错误的位置,我会在长时间运行的代码运行时使用日志记录或 jstack 从服务器获取堆栈跟踪。每隔几秒钟抓取一些堆栈跟踪,然后通过Samurai运行日志文件以查找代码在做什么。

于 2012-05-09T13:21:23.880 回答
3

当您知道 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应该出现的超时错误之后而不是进一步执行代码。

于 2012-07-25T09:31:23.277 回答
2

我发现和亨利一样的东西。这是我的测试代码:

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 分钟。也就是说,线程不是“请求”,所以我不确定我是否希望它遵守请求超时。没有任何记录表明我可以发现它应该尊重请求超时。也就是说......有某种杀死线程的方法将是“方便的”。

我想这只是我认为您的期望不正确的上下文中的“答案”,因为您希望它尊重请求超时。

于 2012-05-09T08:44:41.073 回答