生存期租约
本主题介绍一项传统技术,保留该技术是为了向后兼容现有的应用程序,不建议对新的开发使用该技术。现在应该使用 Windows Communication Foundation (WCF) 来开发分布式应用程序。
无论引用封送对象 (MBR) 是服务器激活的 Singleton 对象还是客户端激活的对象,它们都不会永远驻留在内存中。实际上,每个 MBR 都有一个生存期,此生存期由租约、租约管理器和许多主办方共同控制,除非类型将 MarshalByRefObject.InitializeLifetimeService 重写为控制其自己的生存期策略。在这种情况下,MBR 对象的生存期就是该对象在内存中保持活动状态的总时间。租约是指特定对象在内存中保持活动状态,直至 .NET Framework 远程处理系统开始删除该对象并回收内存这一过程的时间段。服务器应用程序域的租约管理器是指决定何时将远程对象标记为等待垃圾回收的对象。主办方是指可通过在租约管理器中注册自身来为特定对象请求新租约的对象。
只要在应用程序域之外远程处理 MBR 对象,就会为该对象创建生存期租约。每个应用程序域都包含一个租约管理器,负责管理其域内的租约。租约管理器会定期在所有租约中检查过期的租约时间。当某个租约过期时,租约管理器将向该对象的一系列主办方发送一个请求,以查询是否有任何主办方要负责续订该租约。如果没有主办方续订该租约,租约管理器就会移除该租约,这样相关对象将被删除,其内存也将由垃圾回收加以回收。因此,如果有主办方多次续订租约,或者对象不断由客户端调用,对象的生存期则可远远超过其生存期租约的期限。
远程对象的生存期与其客户端的生存期无关。基本对象的租约可以很长,在这种情况下,该对象可能由多个客户端使用。对象的租约可由客户端定期续订,从而延长该对象的生存期。这种方法使分布式垃圾回收只需要很少的网络流量,因而可以有效地提高租约的使用效率。但是,对于使用短缺资源的远程对象,其租约规定的生存期可能会很短,此时客户端经常是每隔一小段时间便续订一次。当所有客户端都处理完该远程对象后,.NET Framework 远程处理系统会迅速将该对象标记为等待垃圾回收。这种策略可以降低网络流量,从而提高服务器资源的使用效率。
使用租约来管理远程对象的生存期是引用计数的一种替代方法。当网络连接不可靠时,引用计数会变得复杂而缺乏效率。虽然租约在经过配置后可使远程对象的生存期超过所需的准确长度,但它也能减少专门用于引用计数以及向客户端发送请求的网络流量,因此只要在特定的方案中配置得当,租赁将是一个很有吸引力的解决方案。
下表描述了租约的主要属性。
属性 | 说明 |
---|---|
InitialLeaseTime |
指定在租约管理器开始对象删除过程之前,该对象保留在内存中的初始时间跨度。在配置文件中,它是 <lifetime> 元素 配置元素的 leaseTime 特性。默认值为 5 分钟。租约时间为 0 会将租约设置为无限生存期。 |
CurrentLeaseTime |
指定租约过期前剩余的时间跨度。续订租约时,其 CurrentLeaseTime 将被设置为 CurrentLeaseTime 或 RenewOnCallTime 的最大值。 |
RenewOnCallTime |
指定每次远程调用对象后为 CurrentLeaseTime 设置的最大时间跨度。默认值为 2 分钟。 |
SponsorshipTimeout |
指定租约管理器得到租约过期通知时等待主办方响应的时间。如果主办方未能在指定时间内响应,将移除该主办方并调用另一个主办方。如果没有其他主办方,租约将过期,远程对象将被标记为等待垃圾回收。如果值为 0 (TimeSpan.Zero),租约将不注册主办方。默认值为 2 分钟。 |
LeaseManagerPollTime |
指定租约管理器在检查完过期租约后休眠的时间。默认值为 10 秒。 |
当在另一个应用程序域中激活 MBR 对象时,将创建租约。此时,如果 ILease.CurrentState 属性为 LeaseState.Initial,就可以设置租约属性。完成设置后,不能直接对它们进行更改。您只能更改 CurrentLeaseTime,方法是调用 ILease.Renew,或者等到租约管理器对主办方调用 ISponsor.Renewal 而主办方用 TimeSpan 对象响应时再进行更改。MarshalByRefObject 包含生存期租约的默认实现,如果在创建租约时未对此租约进行修改,该租约的属性将始终不变。
修改租约属性
生存期租约属性可通过下列方式进行修改:
通过重写 MBR 对象中的 MarshalByRefObject.InitializeLifetimeService,以手动设置租约的属性或返回 null 引用(在 Visual Basic 中为 Nothing),声明自定义生存期租约属性。后一种方法会让 .NET Framework 远程处理系统获知,此类型的实例具有无限生存期。
在应用程序或计算机配置文件中,开发人员或管理员还可以使用 <lifetime> 元素 元素为特定应用程序中的所有对象指定生存期属性。有关更多信息,请参见初始化租约。
租约在创建后可通过下列方式续订:
客户端直接调用 Renew。
如果设置了 ILease.RenewOnCallTime 属性,对远程对象的每次调用都会将租约续订指定的时间。
有关详细信息,请参见 续订租约。
租约管理器
租约管理器必须定期检查租约是否过期。当租约过期时,租约将得到通知并尝试通过调用其主办方来续订自身。
租约管理器还维护着一个主办方列表,租约正等待这些主办方给予响应。如果主办方未能在 SponsorshipTimeout 时间跨度指定的间隔内响应,则从主办方列表中将其移除。
请注意,恶意远程处理客户端可能会滥用租约系统,并对远程处理服务器发起拒绝服务 (DOS) 攻击。恶意客户端会发起许多租约,然后拒绝响应服务器的续订查询。只有 TypeFilterLevel 设置为最大时,才可能出现这种 DOS 攻击。
当允许租约过期时,将不再接受其他租约消息或主办方响应。租约引用将被从租约列表中移除,.NET Framework 远程处理系统还会从其内部表中移除该对象引用。随后,垃圾回收系统将移除该租约和对象。
另请参见
任务
如何:重写 InitializeLifetimeService 接口
如何:续订租约
参考
远程处理设置架构
ILease
RemotingServices.GetLifetimeService
MarshalByRefObject.InitializeLifetimeService