我想帮助确定为什么这个特殊代码在极少数情况下会产生竞争条件。我找到了一个解决方案,我也会概述,但我真的想了解它。
我们有一个基于CMS的系统,包含许多基于保险箱模型的模块。一切都通过一个index.cfm。
在我们的Index.cfm中,我们创建了几个Components实例,其中一些实例是在Application.cfc中创建的APPLICATION.PortalApp实例上。我不包括该代码,因为它并不完全相关:
<cfset REQUEST.ActionHandler = CreateObject("Component", "Components.ActionHandler").init(APPLICATION.PortalApp.Config) />
<cfset VARIABLES.Modules = CreateObject("Component", "Components.Modules").init(APPLICATION.PortalApp.Config, REQUEST.ActionHandler.GetModuleList(), REQUEST.ActionHandler.GetSuppressOutput(), REQUEST.ActionHandler.GetRoleList(), REQUEST.ActionHandler.GetAccessList(), REQUEST.ActionHandler.GetMasterRoleList()) />
在我们实例化这些对象之后,我们通过调用PageManager组件来获取页面上模块的内容(基于它们的&#39;上下,左,中,右)。实例化为Application.PortalApp。
的应用程序的一部分<cfsavecontent variable="Variables.Portal_Content.Top"><cfset APPLICATION.PortalApp.PageManager.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 0 ) /></cfsavecontent>
<cfsavecontent variable="Variables.Portal_Content.Left"><cfset APPLICATION.PortalApp.PageManager.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 1 ) /></cfsavecontent>
<cfsavecontent variable="Variables.Portal_Content.Middle"><cfset APPLICATION.PortalApp.PageManager.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 2 ) /></cfsavecontent>
<cfsavecontent variable="Variables.Portal_Content.Right"><cfset APPLICATION.PortalApp.PageManager.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 3 ) /></cfsavecontent>
PageManager.DisplayContent基本上遍历模块并将它们包装在一个包装器中。但是,在某些时候,存在竞争条件和功能陨石坑并且根本不显示任何模块。它似乎是基于VARIABLES.Modules变得腐败但是在VARIABLES范围内没有共享。
要解决此问题,我们将代码更改为以下内容:
<!--- If we do not use VARIABLES scope and create a ContentManager, race condition can cause empty modules --->
<cfset VARIABLES.CurrPageMgr = CreateObject("Component", "Components.ContentManager").init() />
<cfsavecontent variable="Variables.Portal_Content.Top"><cfset VARIABLES.CurrPageMgr.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 0 ) /></cfsavecontent>
<cfsavecontent variable="Variables.Portal_Content.Left"><cfset VARIABLES.CurrPageMgr.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 1 ) /></cfsavecontent>
<cfsavecontent variable="Variables.Portal_Content.Middle"><cfset VARIABLES.CurrPageMgr.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 2 ) /></cfsavecontent>
<cfsavecontent variable="Variables.Portal_Content.Right"><cfset VARIABLES.CurrPageMgr.DisplayContent( SESSION, REQUEST.ActionHandler, VARIABLES.Modules, 3 ) /></cfsavecontent>
ContentManager的DisplayContent是与PageManager.DisplayContent完全相同的函数文本,ContentManager上的例外仅存在于VARIABLES范围内,而PageManager作为APPLICATION的一部分存在。
在获得报告后很难再现。我基本上开始了一个jmeter会话锤击开发服务器尽可能地使用断点设置基于我知道会用VARIABLES触发的条件。模块已损坏。这是重现它的唯一方法。
我也不是100%确定这个修复工作正常,但到目前为止,jmeter还没有解决这个问题。
编辑:每个请求,DisplayContent函数:
<cffunction name="displayContent" access="public" output="true">
<cfargument name="SessionData" required="yes" type="Struct" />
<cfargument name="ActionHandler" required="yes" type="ActionHandler" />
<cfargument name="Modules" required="yes" type="Modules" />
<cfargument name="Pane" required="yes" type="numeric" />
<cfswitch expression="#Arguments.Pane#">
<cfcase value="1"><cfset Variables.blnPane = ARGUMENTS.Modules.getLeft()></cfcase>
<cfcase value="2"><cfset Variables.blnPane = ARGUMENTS.Modules.getCenter()></cfcase>
<cfcase value="3"><cfset Variables.blnPane = ARGUMENTS.Modules.getRight()></cfcase>
<cfdefaultcase><cfset Variables.blnPane = ARGUMENTS.Modules.getTop()></cfdefaultcase>
</cfswitch>
<cfif VARIABLES.blnPane>
<cfset VARIABLES.qryPaneModules = ARGUMENTS.Modules.GetModulesInPane(Arguments.Pane)>
<cfset VARIABLES.aryModulesInPane = ArrayNew(1)>
<cfloop query="VARIABLES.qryPaneModules">
<cfset VARIABLES.blnResult = ArrayAppend(aryModulesInPane,VARIABLES.qryPaneModules.MOD_SYS_NR)>
</cfloop>
<cfset VARIABLES.Template = "../CustomTags/Portalv#ARGUMENTS.SessionData.intPortalVersion#/DisplayModuleAlternate.cfm">
<cfif Arguments.ActionHandler.GetDocumentType() EQ 3>
<cfset VARIABLES.Template = "../CustomTags/Portalv#ARGUMENTS.SessionData.intPortalVersion#/DisplayXMLModule.cfm">
</cfif>
<cfif VARIABLES.qryPaneModules.recordcount GT 0>
<cfloop index="VARIABLES.modLoop" from="1" to="#ArrayLen(VARIABLES.aryModulesInPane)#">
<cfparam name="VARIABLES.aryModulesInPane[VARIABLES.modLoop]" default="0">
<cfset VARIABLES.objModuleInfo = ARGUMENTS.Modules.GetModuleInfo( VARIABLES.aryModulesInPane[VARIABLES.modLoop], ARGUMENTS.Modules.GetModules() ) />
<cfif NOT IsNumeric(VARIABLES.objModuleInfo.intModuleID)>
<cfset VARIABLES.objModuleInfo.intModuleID = 0 >
</cfif>
<cfmodule template="#VARIABLES.Template#"
ModuleID="#VARIABLES.objModuleInfo.intModuleID#"
ModuleName="#VARIABLES.objModuleInfo.strModuleName#"
SecurityLevel="#VARIABLES.objModuleInfo.intRoleTypeID#"
ModuleDSN="#VARIABLES.objModuleInfo.strModDBDSN#"
ModuleUserName="#VARIABLES.objModuleInfo.strModDBUserID#"
ModulePassword="#VARIABLES.objModuleInfo.strModDBPassword#"
AlternateFunctionID="#VARIABLES.objModuleInfo.intAlternateFunctionID#"
AlternateFunctionName="#VARIABLES.objModuleInfo.strAlternateFunctionName#"
InstructionFileID="#VARIABLES.objModuleInfo.intManualID#"
ModuleOps="#VARIABLES.objModuleInfo.blnModuleOps#"
ModuleSource="#VARIABLES.objModuleInfo.strModuleSource#"
ItemID="#VARIABLES.objModuleInfo.intModItemID#"
AutoLoginID="#VARIABLES.objModuleInfo.intAutoLoginCategoryID#"
IPS_objPortalSessionData="#ARGUMENTS.SessionData#"
ModuleList="#ARGUMENTS.ActionHandler.GetModuleList_SingleRecord(VARIABLES.objModuleInfo.intModuleID)#"
ModulesComponent="#ARGUMENTS..Modules#"
ControlHeaderIR = "#VARIABLES.objModuleInfo.blnControlHeaderIR#"
BorderIR = "#VARIABLES.objModuleInfo.blnBorderIR#"
IPS_strPortalRoot = "#VARIABLES.IPS_strPortalRoot#"
IPS_strPortalURL = "#VARIABLES.IPS_strPortalURL#"
Wrapper = "#Arguments.ActionHandler.getWrapper()#"
Definition = "#VARIABLES.objModuleInfo.strModuleDef#"
Category = "#VARIABLES.objModuleInfo.strModuleCat#"
aryModulesInPane = "#VARIABLES.aryModulesInPane#"
blnLockIR = "#VARIABLES.objModuleInfo.blnLockIR#"
strMessageTE = "#VARIABLES.objModuleInfo.strMessageTE#" >
</cfloop>
</cfif>
</cfif>
</cffunction>
答案 0 :(得分:1)
在PageManager组件的DisplayContent函数中使用VARIABLES范围(它已被实例化为Application的一部分,因此共享)是问题所在。在这种情况下,VARIABLES范围将被共享,从而导致竞争条件。
除了在另一个组件中复制该函数并在index.cfm的VARIABLES范围内实例化之外,您还可以从DisplayContent函数中的VARIABLES范围切换到LOCAL范围(假设您不需要访问这些范围)函数之外的变量)。当使用jmeter进行压力测试时,两种方式都不会再次出现竞争状态。