将 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
组件:
- 'cleans' 用户提交的任何图片和文字
- 将图像放在正确的文件夹中
- 将所有文本写入数据库
- returns一个URL可以查看post
返回的 URL 由简单的 Jquery ajax 调用接收,该调用将用户重定向到 URL.
这种情况在网站上经常发生,目前正在为每个 post 创建一个新的 CFC 实例。将它放在 Application 范围内而不导致 race/locking 条件是否安全?
仅仅传递参数不会"save"任何东西。从概念上讲,每个线程都有自己的 arguments
和 local
范围,这些范围对任何其他线程都不可见,并且在函数退出时不复存在。所以从这个角度来说,没有冲突。
此外,存储数据并不意味着将其保存到数据库中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;
在你的情况下,听起来大部分信息都没有共享,并且是请求级别的(用户信息、上传的图像等),因此存储在应用程序范围内可能是安全的。
我已经阅读了很多关于在应用程序范围内存储 CFC 的 post,并且我明白如果 CFC 存储数据那么它不应该在应用程序范围内。所有执行非实用程序的 CFC 都会存储数据 - 当您传入用户名或电子邮件地址等参数时 - 所以我不知道何时以及何时不使用非实用程序 cfc 的应用程序范围。
我的问题是我有一个大约 500 行代码的 posthandler.cfc
组件,它处理来自用户的 posts(就像 SO 会处理每个被 posted 的问题一样在这个网站上)。 posthandler.cfc
组件:
- 'cleans' 用户提交的任何图片和文字
- 将图像放在正确的文件夹中
- 将所有文本写入数据库
- returns一个URL可以查看post
返回的 URL 由简单的 Jquery ajax 调用接收,该调用将用户重定向到 URL.
这种情况在网站上经常发生,目前正在为每个 post 创建一个新的 CFC 实例。将它放在 Application 范围内而不导致 race/locking 条件是否安全?
仅仅传递参数不会"save"任何东西。从概念上讲,每个线程都有自己的 arguments
和 local
范围,这些范围对任何其他线程都不可见,并且在函数退出时不复存在。所以从这个角度来说,没有冲突。
此外,存储数据并不意味着将其保存到数据库中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;
在你的情况下,听起来大部分信息都没有共享,并且是请求级别的(用户信息、上传的图像等),因此存储在应用程序范围内可能是安全的。