Coldfusion 阵列中丢失项目

发布于 2024-11-18 00:40:05 字数 1923 浏览 2 评论 0原文

这让我发疯。我们尝试构建一个 CF memcached 包装器。我们有一个像这样的 memcached.cfc 组件:

<cfset this.m = arraynew(1)>

<cffunction name="init" access="public" output="false">
    <cfif not isdefined("application.memcached")
    ....
            <cfscript>
            setup();
                </cfscript>
         ...
            <cfset application.memcached = this>
          </cfif>
   <cfreturn application.memcached>
</cffunction>


<cffunction name="setup" access="private" output="false">
    <cftry>
        <cfset this.m = arraynew(1)>
        <cfloop from="1" to="#this.poolSize#" index="i">
            <cfset this.m[i] = createClient()>
        </cfloop>
        <cflog application="no" file="memcached" text="Successfully set up #this.poolSize# new memcache clients">
        <cfcatch>
            <cflog application="no" file="memcached" text="Exception in setup() while setting up the pool: type: #cfcatch.type#, message: #cfcatch.message#, detail: #cfcatch.detail#">
        </cfcatch>
    </cftry>
</cffunction>


<cffunction name="createClient" access="private" output="false">
    <cfset var AU = createObject("java", "net.spy.memcached.AddrUtil").init()>
    <cfset var c = createObject("java", "net.spy.memcached.MemcachedClient").init(AU.getAddresses("127.0.0.1:11211"))>
    <cfreturn c>
</cffunction>

<cffunction name="getCache" access="public" returntype="any" output="false">
    <cfset idx = ceiling(rand() * 20)>
    <cfreturn application.memcached.m[idx]>
</cffunction>

奇怪的是,运行了 30 分钟左右后,getCache 开始失败,表示 application.memcached.m 数组中的 idx 位置没有项目。

怎么会发生这种事? CF 数组是否使用弱引用或其他什么?当然,一旦阵列填充了 20 个客户端,阵列就应该始终保持满状态吗?

每个新客户端都会生成一个新线程,因此一旦我们失去了对客户端的引用,现在就有办法将其关闭,并且该线程永远驻留在那里并占用内存。请问,我错过了什么?

This is driving me crazy. We have tried to build a CF memcached wrapper. We have a memcached.cfc component like this:

<cfset this.m = arraynew(1)>

<cffunction name="init" access="public" output="false">
    <cfif not isdefined("application.memcached")
    ....
            <cfscript>
            setup();
                </cfscript>
         ...
            <cfset application.memcached = this>
          </cfif>
   <cfreturn application.memcached>
</cffunction>


<cffunction name="setup" access="private" output="false">
    <cftry>
        <cfset this.m = arraynew(1)>
        <cfloop from="1" to="#this.poolSize#" index="i">
            <cfset this.m[i] = createClient()>
        </cfloop>
        <cflog application="no" file="memcached" text="Successfully set up #this.poolSize# new memcache clients">
        <cfcatch>
            <cflog application="no" file="memcached" text="Exception in setup() while setting up the pool: type: #cfcatch.type#, message: #cfcatch.message#, detail: #cfcatch.detail#">
        </cfcatch>
    </cftry>
</cffunction>


<cffunction name="createClient" access="private" output="false">
    <cfset var AU = createObject("java", "net.spy.memcached.AddrUtil").init()>
    <cfset var c = createObject("java", "net.spy.memcached.MemcachedClient").init(AU.getAddresses("127.0.0.1:11211"))>
    <cfreturn c>
</cffunction>

<cffunction name="getCache" access="public" returntype="any" output="false">
    <cfset idx = ceiling(rand() * 20)>
    <cfreturn application.memcached.m[idx]>
</cffunction>

The weird thing is that after running for 30 minutes or so, the getCache starts failing says that there is no item in the application.memcached.m array at position idx.

How could this be happening? Are CF arrays using weak references or something? Surely once the array is populated with 20 clients the array should stay full always?

Each new client spawns a new thread so once we lose the reference to the client there is now way to shut it down and that thread lives there forever taking memory. Please, what am i missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

趁微风不噪 2024-11-25 00:40:05

也许您的应用程序范围被删除。您应该为此指定适当的超时。无论 OnApplication 是否被调用,您都应该记录下来以进行调试。

Maybe your application scope gets deleted. You should specify a proper timeout for that. You should also log this whether OnApplication gets called or not for debugging purposes.

你在我安 2024-11-25 00:40:05

什么时候使用这个memcached CFC?每个请求? 'i' 和 'idx' 变量缺乏 var 作用域可能与此有关。这是我写的几篇文章,简单演示了为什么这是必要的。

http://duncan99.wordpress.com/2009/ 03/12/var-scoping 的重要性/

http://duncan99.wordpress.com/ 2009/03/16/var-scoping-part-2 的重要性/

When does this memcached CFC get used? Every request? The lack of var scoping on the 'i' and 'idx' variables could well have something to do with it. Here's a couple of articles I wrote that do a simple demonstration of why this is essential.

http://duncan99.wordpress.com/2009/03/12/the-importance-of-var-scoping/

http://duncan99.wordpress.com/2009/03/16/the-importance-of-var-scoping-part-2/

赠我空喜 2024-11-25 00:40:05

答案可能相当简单 - 事实上,此类的任何实例化都会立即使应用程序范围内的数组无效,这使得该类的管理相当麻烦。此外,虽然间谍 memcached 驱动程序本身表现为单例,并且数组 (java.util.vector) 是线程安全的,但此实现的其他任何内容都不是 - 不是应用程序范围,绝对不是 cfc 实例。

假设您可以消除 getCache() 函数中 idx 的越界值(我假设您已经这样做了,如果没有,请在函数中抛出一个 try/catch 块并在抛出异常时报告 idx 是什么),您通过在构造函数和 getCache() 方法周围使用同名的独占 cflock,可以补救症状,而无需真正解决原因。这样,即使您的类有随机实例化,当有东西试图访问它时,您也永远无法将数组吹出,并且在重新创建它时您将无法尝试访问它。这根本不是一个最佳解决方案,如果您遇到高并发性,您会注意到响应时间略有增加(可以忽略不计,但取决于您每秒服务的请求数,它肯定会对最大吞吐量产生影响。

The answer is probably something fairly simple - the fact that any instantiation of this class will immediately invalidate the array in the application scope makes this a fairly troublesome class to manage. In addition, while the spy memcached driver itself behaves as a singleton, and the array (java.util.vector) is thread-safe, nothing else about this implementation is - not the app scope, definitely not the cfc instance.

Assuming you can eliminate an out of bounds value for idx in the getCache() function (which I assume you already did, if not, throw a try/catch block in the function and report what idx is when the exception is thrown), you can remedy the symptoms without actually addressing the cause by using exclusive cflocks with the same name around the constructor and the getCache() method. This way even if you have random instantiations of your class, you won't ever be able to blow the array out while something is trying to access it, and you won't be able to attempt to access it while it's being re-created. This is not an optimal solution at all, and if you experience high concurrency you will notice a slight elevation in response times (fairly negligible, but depending on how many requests/sec you serve, it can definitely have an impact on max throughput.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文