2016-04-29 4 views
4

Я бы хотел, чтобы некоторые из них помогли определить, почему этот конкретный код, в редких случаях, создает состояние гонки. Я нашел исправление, которое я также опишу, но я действительно хочу это понять.ColdFusion VARIABLES Состояние гонки?

У нас есть система на основе CMS, состоящая из многих модулей, свободно основанных на модели Fusebox. Все проходит через один index.cfm.

В нашем Index.cfm мы создаем пару экземпляров Компонентов, некоторые из них исполняются на экземпляре APPLICATION.PortalApp, созданном в Application.cfc. Я не включая этот код, потому что это не совсем уместным:

<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, который был создан как часть приложения 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> 

DisplayContent из ContentManager является точно такой же функции текста как PageManager.DisplayContent за исключением о существующих только в ПЕРЕМЕННЫХ объеме и PageManager ContentManager существующий как часть ПРИМЕНЕНИЯ.

Это было очень трудно воспроизвести после получения сообщений об этом. Я по сути запустил сессию jmeter, забив сервер разработки так сильно, насколько это возможно, с помощью набора точек останова, основанного на условии, которое, как я знал, будет срабатывать с помощью VARIABLES.Module получил коррумпированность. Это был единственный способ воспроизвести его.

Я также не уверен на 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> 
+1

Похоже, что в 'DisplayContent' есть что-то (переменная без пробела или отсутствующая блокировка и т. Д.), Что вызывает проблему, особенно когда вы ее создаете для каждого запроса, кажется, исправить ее. Вам нужно будет увидеть код DisplayContent для дальнейшего изучения. –

+0

@JohnWhish Добавлена ​​функция ... – Brad

+1

Если этот компонент хранится в области приложения, то хранение чего-то в его области «variables» по существу совпадает с хранением его в области приложения. – Leigh

ответ

1

Использование рамки переменных внутри функции DisplayContent компонента PageManager (который был экземпляр в качестве части приложения, таким образом, общий), был вопрос. Область VARIABLES будет разделяться в этом случае, приводя к условиям гонки.

Вне дублирования этой функции в другом компоненте и ее экземпляра в области VARIABLES индекса index.cfm вы также можете переключиться с области VARIABLES в функции DisplayContent на область LOCAL (при условии, что вам не нужен доступ к эти переменные вне функции). Оба способа удерживали состояние гонки от повторного появления при стресс-тестировании с помощью jmeter.

+1

Да. Запись в область «variables» делает состояние компонента * ful * и, следовательно, подвержена условиям гонки при хранении в общей области, такой как приложение, поскольку область «variables» теперь доступна для нескольких потоков. Как правило, только общие компоненты без сохранения должны храниться в общих областях. Для компонентов состояния * ful * обычно вы должны создать отдельный экземпляр запроса, чтобы переменные не были доступны и доступны другим запросам. – Leigh

Смежные вопросы