将 CFC 用户内容处理程序存储在应用程序范围内是否安全?

Is it safe to store an CFC user content handler in the Application scope?

我已经阅读了很多关于在应用程序范围内存储 CFC 的 post,并且我明白如果 CFC 存储数据那么它不应该在应用程序范围内。所有执行非实用程序的 CFC 都会存储数据 - 当您传入用户名或电子邮件地址等参数时 - 所以我不知道何时以及何时不使用非实用程序 cfc 的应用程序范围。

我的问题是我有一个大约 500 行代码的 posthandler.cfc 组件,它处理来自用户的 posts(就像 SO 会处理每个被 posted 的问题一样在这个网站上)。 posthandler.cfc 组件:

返回的 URL 由简单的 Jquery ajax 调用接收,该调用将用户重定向到 URL.

这种情况在网站上经常发生,目前正在为每个 post 创建一个新的 CFC 实例。将它放在 Application 范围内而不导致 race/locking 条件是否安全?

仅仅传递参数不会"save"任何东西。从概念上讲,每个线程都有自己的 argumentslocal 范围,这些范围对任何其他线程都不可见,并且在函数退出时不复存在。所以从这个角度来说,没有冲突。

此外,存储数据并不意味着将其保存到数据库中table。它指的是通过将数据存储在共享 scope/object/etc 中来维护状态的组件。"shared" 意味着该资源可供 other 线程访问,并且可能会被修改多个线程同时运行,导致竞争条件。

例如,以 variables 范围内的 "saves" 信息的这个(人为的)组件函数为例。如果您每次都创建该组件的新实例,则该函数是安全的,因为每个请求都有自己的实例和单独的 variables 作用域副本。

 public numeric function doStuff( numeric num1, numeric num2 ) {
    variables.firstNum = arguments.num1 * 12;
    variables.secondNum = arguments.num2 * 10;

    return variables.firstNum / variables.secondNum;
 }

现在将相同的组件放入应用程序范围内。它不再安全。一旦将它存储在 application 范围内,该实例 - 及其 variables - 也将成为应用程序范围。因此,当函数 "saves" 数据到 variables 范围时,它实际上是在更新 application 变量。显然这些不是线程安全的,因为 all 请求可以访问它们。因此多个线程可以很容易地同时 read/modify 相同的变量,从而导致竞争条件。

// "Essentially" becomes this .... 
public numeric function doStuff( numeric num1, numeric num2 ) {
    application.firstNum = arguments.num1 * 12;
    application.secondNum = arguments.num2 * 10;

    return application.firstNum / application.secondNum;
}

此外,与 一样,当您省略范围时也会出现同样的问题。 声明一个没有范围的函数变量不会使其成为函数的局部变量。它使其成为默认范围的一部分:variables -(产生与上述相同的线程安全问题)。当开发人员忘记限定单个查询变量甚至循环索引的范围时,这种行为导致了许多线程错误。所以一定要明确地限定每个函数变量的范围。

 // Implicitly creates "variables.firstNum" and "variables.secondNum"
 public numeric function doStuff( numeric num1, numeric num2 ) {
    firstNum = arguments.num1 * 12;
    secondNum = arguments.num2 * 10;

    return firstNum / secondNum;
 }

除了添加锁定之外,这两个示例都可以通过 显式 使用 local 作用域来实现线程安全。通过将数据存储在瞬态 local 范围内,它对其他线程不可见,并且一旦函数退出就不再存在。

 public numeric function doStuff( numeric num1, numeric num2 ) {
    local.firstNum = arguments.num1 * 12;
    local.secondNum = arguments.num2 * 10;

    return local.firstNum / local.secondNum;
 }

显然还有其他情况需要考虑,例如通过引用传递的复杂对象或结构,以及这些对象是否在函数内被修改。但希望这能阐明 "saving data" 的含义,以及作用域如何区分 stateless 组件(对于 application 范围是安全的)和 state ful 个组件(不是)。

TL;DR;

在你的情况下,听起来大部分信息都没有共享,并且是请求级别的(用户信息、上传的图像等),因此存储在应用程序范围内可能是安全的。