📄 在电子商务环境中通过使用对象池获得可伸缩性.htm
字号:
IObjectContext* pObjectContext;
// get our context
HRESULT hr = GetObjectContext(&pObjectContext);
if (FAILED(hr))
return hr;
// now get the ContextState for future use
hr = CoGetObjectContext(IID_IContextState,
(void **)&m_pContextState);
if (FAILED(hr))
{
pObjectContext->Release();
return hr;
}
return hr;
}
void Deactivate()
{
m_pContextState->Release();
}
BOOL CanBePooled()
{
return !m_bErrorState; // if not in error state,
// can be pooled
}
};
</PRE>
<H3>在 COM+ 中安装池化对象</H3>
<P>为了配置池化组件,您可以使用组件服务管理工具或者管理对象模型。在您配置组件之前,应该确定它编写正确,可以支持池。 </P>
<P>默认情况下,组件不能池化。在您配置组件使其池化后,您可以指定几个决定 COM+ 如何维护池的属性。这些属性是: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><I>池的最小大小。</I>这代表了应用程序启动时所创建的对象数量,以及应用程序运行时池中维护的对象最小数量。如果池中可用对象的数量低于指定的最小值,则创建新的对象满足任何未完成对象请求并再次填充池。如果池中可用对象的数量大于最小数量,那些多余的对象将在清除循环中被销毁。
</P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><I>池的最大大小。</I>这代表了池管理器将创建的最大池化对象数量,包括客户端使用的活动对象和池中不活动的对象。当创建对象时,池管理器查看是否已经达到池的最大大小,如果没有,池管理器创建一个新的对象实例分配给客户端。如果已经达到池的最大大小,客户端请求将排入队列,并按照先到先服务的顺序从池中获得第一个可用的对象。对象创建请求将在指定时间后超时。
</P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><I>创建请求超时值。</I> 这将指定客户端等待调用 CoCreateInstance
后,对象从池中返回的时间,以毫秒为单位。如果客户端调用不成功,则返回错误 E_TIMEOUT。 </P></TD></TR></TBODY></TABLE>
<P><B>设置池相关的属性</B></P>
<P>要设置池相关的属性: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0 class=numberedList>
<TBODY>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>1.</P></TD>
<TD>
<P>在 Component Services 管理工具的详细信息窗格中,右击您想要配置的组件,然后单击 <B>Properties</B>。
</P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>2.</P></TD>
<TD>
<P>在组件属性对话框中,单击 <B>Activation</B> 选项卡。 </P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>3.</P></TD>
<TD>
<P>要为组件启用对象池,选择 <B>Enable object pooling</B> 复选框,如图 4 所示。 </P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>4.</P></TD>
<TD>
<P>在 <B>Minimum pool size </B>框中,输入池中此类型对象的最小数量。池将保持至少包含这么多对象。 </P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>5.</P></TD>
<TD>
<P>在 <B>Maximum pool size</B>
框中输入池中此类型对象的最大数量。对象的数量(包括激活的和停用的),将永远不会超过这个值。 </P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>6.</P></TD>
<TD>
<P>在 <B>Creation timeout (ms)</B>
框中,输入时间值,以毫秒为单位,如果不能立即得到的话,这是客户端将等待池化对象的时间。 </P></TD></TR></TBODY></TABLE>
<DIV style="WIDTH: 416px"><IMG alt=scalobjpool4.gif border=0 height=464
src="在电子商务环境中通过使用对象池获得可伸缩性.files/scalobjpool4.gif" width=416><BR>
<P class=figureCaption><B>图 4. Component Services Object Pooling 对话框</B></P>
<DIV class=figureRule></DIV></DIV>
<DIV style="MARGIN-BOTTOM: 10px; MARGIN-TOP: 3px"><A
href="http://www.microsoft.com/china/msdn/library/windev/componentdev/CDscalobjpool.mspx#top"><IMG
alt=返回页首 border=0 height=9 src="在电子商务环境中通过使用对象池获得可伸缩性.files/arrow_px_up.gif"
width=7></A><A class=topOfPage
href="http://www.microsoft.com/china/msdn/library/windev/componentdev/CDscalobjpool.mspx#top">返回页首</A></DIV><A
name=XSLTsection124121120120></A>
<H2>实时激活</H2>
<P>实时 (JIT) 激活,是 COM+ 提供的一种自动服务,可以帮助您更高效地使用服务器资源,尤其是在扩展您的应用程序执行大容量事务的时候。当组件被配置为
JIT 激活时,COM+ 将在客户端仍然拥有对象的活动引用时,不时地使实例停用。下一次客户端调用对象的方法时,它仍然相信对象是活动的,COM+
将重新激活对象,这对于客户端是透明的,也即所谓<I>实时</I>。 </P>
<P>使用 JIT 激活的优点是使客户端只要需要就能够拥有对象的引用,从而没有必要占用服务器资源(如内存)来做这件事。其他优点如下: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>从客户端的角度来看它极大地简化了编程模型。客户端不必考虑如何使用昂贵的服务器对象。没有 JIT
激活,客户端必须考虑如何使用服务器资源。当客户端对于释放服务器对象过于积极的时候,它们可能会因为频繁调用和释放对象而招致重大惩罚。
</P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>它可以显著地改善您应用程序的性能。通过保存生命期较长的对象引用,客户端只要它们需要就对对象保持通道打开。客户端距离服务器越远,激活和封送处理服务器对象的成本也更高
—
打开通道,设置代理和存根,等等。对于分布式的应用程序,每次对象创建都需要昂贵的网络往返行程。随着客户端调用量的增加,您想要最大限度地降低对象创建的频率,因为它会显著地影响应用程序的性能。
</P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>它可以释放服务器内存。如果客户端保存的对象引用生命期较长,没有必要总是使用,对这些对象 JIT
激活能够使这些对象不用总是生存,从而确保不会总是占用服务器内存。这称为惰性激活,因为内存只在对象实际需要的时候才使用。这可以显著地增加您应用程序的可伸缩性。客户端能看到的唯一性能降低的方面是它使用
COM+ 重新激活对象要花费时间,这通常比为对象分配内存要稍微多花一些时间,而这比远程对象创建的网络往返行程花费的时间要少得多。
</P></TD></TR></TBODY></TABLE>
<H3>配置对象以使用 JIT 激活</H3>
<P>要启用 JIT 激活: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0 class=numberedList>
<TBODY>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>1.</P></TD>
<TD>
<P>在 Component Services 管理工具的详细信息窗格中,右击您想要配置的组件,然后单击 <B>Properties</B>。
</P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>2.</P></TD>
<TD>
<P>在组件属性对话框中,单击 <B>Activation</B> 选项卡。 </P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>3.</P></TD>
<TD>
<P>要为组件启用 JIT 激活,选择 <B>Enable Just In Time Activation </B>复选框如图 5 中所示。
</P></TD></TR>
<TR vAlign=top>
<TD align=right class=listNumber noWrap>
<P>4.</P></TD>
<TD>
<P>单击 <B>OK</B>。 </P></TD></TR></TBODY></TABLE>
<DIV style="WIDTH: 416px"><IMG alt=scalobjpool5.gif border=0 height=462
src="在电子商务环境中通过使用对象池获得可伸缩性.files/scalobjpool5.gif" width=416><BR>
<P class=figureCaption><B>图 5. 组件服务 JIT 激活对话框</B></P>
<DIV class=figureRule></DIV></DIV>
<P><B>注</B> 如果组件被配置为需要事务,JIT 激活将被自动启用。当您为组件启用 JIT
激活时,对该组件,它的同步属性将设置为“required”。在这种情况下您不能更改同步设置。</P>
<P>在您已经为组件启用 JIT 激活之后,可以为该组件公开的任何方法选择启用自动完成功能。 </P>
<P>我们现在将探讨如何配置组件以允许它自己被停用,以及 JIT 激活怎样能够与对象池一起使用。 </P>
<H3>使用 JIT 激活</H3>
<P>COM+ 将根据一个上下文属性 — 完成位的状态来停用 JIT 激活的对象,如下所示: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>如果完成位被设置为 TRUE,当前方法调用返回时 COM+ 将停用对象。 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>如果完成位被设置为 FALSE,在当前方法调用返回时,对象将保持活动状态。 </P></TD></TR></TBODY></TABLE>
<P>默认情况下,当创建一个对象,并初始化它的上下文时,完成位被设置为
FALSE。但是,您可以逐个方法地更改这种默认设置,这通过使用自动完成属性进行。设置完成位可以有如下方式: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>通过使用 <B>IContextState::SetDeactivateOnReturn</B></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>通过使用 <B>SetComplete </B>或者 <B>SetAbort </B>的 <B>IObjectContext</B>
方法(这是最常见的方法) </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>通过使用 <B>Auto-Done </B>属性 </P></TD></TR></TBODY></TABLE>
<H3>IContextState</H3>
<P>您可以使用 <B>IContextState::SetDeactivateOnReturn</B> 将完成位设置为 TRUE 或者 FALSE。服务器
C++ 代码可能如下例所示:</P><PRE class=codeSample>HRESULT MyObject::Method1()
{
. . .
IContextState *pContextState;
hr = CoGetObjectContext(IID_IContextState,
&pContextState);
if (FAILED(hr))
return E_FAIL;
if (bDone) // is the object able to be deactivated?
{
pContextState->SetDeactivateOnReturn(FALSE);
}
else
{
pContextState->SetDeactivateOnReturn(TRUE);
}
return S_OK;
}
</PRE>
<P>您可以使用 <B>IContextState::GetDeactivateOnReturn</B> 从对象上下文获取完成位的当前状态。 </P>
<H3>使用 IObjectContext</H3>
<P>您可以使用 <B>IObjectContext</B> 的方法以设置完成位,并同时设置用于在事务中表决的一致位,方法如下: </P>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><B>SetComplete</B> 方法发出信号表示您已经完成而且表决了要提交当前事务。它设置完成位为 TRUE,一致位为 TRUE。
</P></TD></TR>
<TR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -