面向对象设计的一个目标就是将各种功能封装到不同的对象.这种思想很好,鼓励使用封装和委托. 有些应用程序或框架无法预料必须被创建的对象的类型.通常先接收一些信息指示如何执行. 这种情形在RO服务端接收到客户端请求是经常要面对:服务端需要知道请求需要什么对象,需要创建一个实例,最终调用完成, 又需要决定如何处理这个创建的实例. 我们使用类工厂模式来解决这中变异. 注意:本文适合RemObjects SDK的 Delphi和.NET版本. 对只适用于一种版本的将标注. 数据库连接池 很多可用的Delphi架构都是以数据为中心的.这可以适应简单应用,但当需要池和线程安全存取对象时很快就崩溃了. RemObjects SDK提供数据库连接池的支持:允许你线程安全的缓冲服务对象实例. 同时你也可以为你的对象选择其他的实例化模式. 如何控制使用的实例化模式 For Delphi 在xxxx_Impl.pas单元的initialization节中设置适当的类工厂. 下面是MegaDemo 范例的NewService_Impl.pas代码: initialization TROClassFactory.Create('NewService', Create_NewService, TNewService_Invoker); TROClassFactory使用单独调用对象模式激活(per-call). 这意味着每个对NewService的调用都会生成一个新的服务实例,调用支持完毕马上释放.如果你希望对NewService服务生成大小为4的缓冲池,使用如下代码: initialization TROPooledClassFactory.Create('NewService', Create_NewService, TNewService_Invoker, 4); For .NET, RemObjects SDK 在定义服务是使用指定属性, 如. [RemObjects.SDK.Server.ClassFactories.StandardClassFactory()] [RemObjects.SDK.Server.Service(Name="MegaDemoService", InvokerClass=typeof(MegaDemoService_Invoker))] public class MegaDemoService : RemObjects.SDK.Server.Service, IMegaDemoService { 同Delphi的情形,标准的类工厂为每个调用创建一个新实例,调用后马上释放.在.NET中使用缓冲池,可以修改制订属性使用PooledClassFactory属性替换.例如创建缓冲大小为4的实例: [RemObjects.SDK.Server.ClassFactories.PooledClassFactory(4)] 可用的类工厂 类工厂如下表:
SDK可用如下实例化模式和类工厂:
注: |
TROClassFactory/StandardClassFactory 这是默认的类工厂.每当接到请求时,都会在服务端创建一个新实例,执行请求后释放.由于对与每个请求都是在单独进程的单独实例中执行,所以对类内的成员调用都是线程安全的.例如如果在服务对象类中创建一个组件,你可以放心使用它,而不用担心其他线程的锁定. 这种实例化模式是最据可扩展行的,这种思想源于Web情形. For Delphi, 构造函数声明如下: constructor Create(const anInterfaceName: string; aCreatorFunc: TRORemotableCreatorFunc; anInvokerClass: TROInvokerClass); For .NET, 通过订制属性指定所以没有构造函数参数. TROPerClientClassFactory/PerClientClassFactory 这种类工厂保证客户端连续的调用同一个服务对象.对象在客户端第一次连接后创建,在对象闲置时间超过Timeout-seconds后释放. 这种实例化模式可扩展性差并消耗资源. 我们不推荐使用这种模式, 但在开发DataSnap应用时很有用. For Delphi,你也可以通过编程控制对象的释放,对象要实现IRODestructorController接口并让CanBeDestroyed方法返回True.在每次调用后类工厂都会检查这个函数并做相应的操作. TROPerClientClassFactory的构造函数声明如下: constructor Create(const anInterfaceName: string; aCreatorFunc: TRORemotableCreatorFunc; anInvokerClass: TROInvokerClass; aTimeoutSeconds: cardinal); For .NET, PerClientClassFactory 的制订属性没有参数,但有两个域:
TROSingletonClassFactory/SingletonClassFactory 这个类工厂只创建一个服务对象实例,使用时需要自己控制线程安全. 因为不支持线程安全所以使用内部成员时需要人为的增加线程同步控制. 这个实例模式效率很好,但是控制很复杂. 一个实例可能会同时处理多个请求,所以必须重视线程安全. For Delphi, TROSingletonClassFactory 构造函数声明如下: constructor Create(const anInterfaceName: string; aCreatorFunc: TRORemotableCreatorFunc; anInvokerClass: TROInvokerClass); For .NET, 有两个重载的构造函数: public SingletonClassFactoryAttribute() public SingletonClassFactoryAttribute(SingletonBehavior aSingletonBehavior) SingletonBehavior参数可以设置为Multiple, Wait 或 Fail. Multiple (默认)允许多个客户端请求同时在一个服务实例上执行. Wait 选项要等待服务实例空闲时才能处理请求, 保证同时只有一个实例运行. Fail 选项当服务实例正在运行时引发调用错误. TROSynchronizedSingletonClassFactory 这个类工厂只创建一个对象实例,所有请求线程顺序的使用.框架自动为你实现了线程安全和对象内成员访问的线程同步. 这个实例化模式不是很有效率,但是当需要顺序访问外部资源(如访问文件或主机连接)是很有用. TROSynchronizedSingletonClassFactory 构造函数声明如下: constructor Create(const anInterfaceName: string; aCreatorFunc: TRORemotableCreatorFunc; anInvokerClass: TROInvokerClass); TROPooledClassFactory/PooledClassFactory 这个类工厂持有指定数量的对象实例,并提供了线程安全的访问接口. For Delphi, TROPooledClassFactory构造函数声明如下: constructor Create(const anInterfaceName: string; aCreatorFunc: TRORemotableCreatorFunc; anInvokerClass: TROInvokerClass; aPoolSize: Integer; aPoolBehavior:TROPoolBehavior=pbCreateAdditional; aPreInitializePool:Boolean=false); 设置aPreInitializePool参数为TRUE时类工厂创建后将填充线程池. 当请求数量达到最大时, PoolBehavior 参数觉得如何处理.aPoolBehavior可以设置为pbFail, pbWait, 和 pbCreateAdditional. 服务终止后对象被释放. For .NET, 有四个重载的构造函数: public PooledClassFactoryAttribute() public PooledClassFactoryAttribute(int aPoolSize) public PooledClassFactoryAttribute(int aPoolSize, PoolBehavior aPoolBehavior) public PooledClassFactoryAttribute(int aPoolSize, PoolBehavior aPoolBehavior, bool aPreInitializePool) PoolSize参数指定缓冲池的大小. aPoolBehavior 参数可以设置为:
aPreIntializePool参数指定是否在启动时预先生成aPoolSize个服务对象实例. 默认缓冲池大小为5, PoolBehavior 为 Fail, PreInitializePool 为 false. |
RO 可以使用的线程模式有:
1.TROClassFactory:默认的方式,每个连接都建立一个接口对象,用完即销毁。CPU占用率极高(非 ISAPI),比较稳定。
2.TROSingletonClassFactory:单实例模式,所有连接共享一个实例,可能存在线程冲突。
3.TROSynchronizedSingletonClassFactory:同步单实例模式,所有连接共享一个实例但必须一个一个的按顺序访问,是线程安全的模式,但效率低,CPU 占用率也低。
4.TROPerClientClassFactory:每个客户端一个连接(以ClinetID为准),效率高。也可以称为一个Session一个实例,Session在一定时间内不活动就会销毁实例。
5.TROPooledClassFactory:连接池模式,效率很好,但CPU占用率也高些。连接池的大小可以根据情况调节,而且对超过连接池大小的新连接,可以在返回错误、等待或新建实例中选择操作。