生存期租约
引用封送对象 (MBR) 不会永远驻留在内存中,无论是服务器激活的 Singleton 对象还是客户端激活的对象,都是如此。相反,除非该类型重写 MarshalByRefObject.InitializeLifetimeService 以控制它自己的生存期策略,否则每个 MBR 的生存期都由租约、租约管理器和一些主办方的组合来控制。(在这种情况下,MBR 对象的生存期是该对象在内存中处于活动状态的时间总和。)租约是 .NET Framework 远程处理系统开始执行删除某个特定对象并回收内存这一进程之前,该特定对象在内存中处于活动状态的时间。服务器应用程序域的租约管理器是一个对象,它确定何时标记远程对象以进行垃圾回收。主办方是可以通过将其本身注册到租约管理器来为特定对象请求新租约的对象。
只要 MBR 对象在应用程序域之外进行远程处理,就将为该对象创建生存期租约。每个应用程序域都包含一个负责管理其域中的租约的租约管理器。租约管理器定期检查所有租约以确定过期的租约时间。如果租约已过期,租约管理器将向该对象主办方的列表发送一个请求,并查询是否有谁要续订租约。如果没有任何主办方续订该租约,租约管理器将移除该租约,该对象也会被删除,而垃圾回收机制将回收其内存。因此,如果对象被主办方多次续订租约或被客户端持续调用,其生存期可以比其生存期租约长得多。
由于远程对象的生存独立于其客户端的生存,因此简单或轻型对象的租约可以很长,被大量的客户端使用,并且被管理员或客户端定期续订。由于分布式垃圾回收所需的网络通信量很小,因此这种方法可高效地使用租约。但是,使用稀有资源的远程对象可以具有生存期较短的租约,而客户端会以非常短的时间段频繁续订该租约。当所有客户端都完成对远程对象的处理后,.NET Framework 远程处理系统将很快删除该对象。这种策略增加了网络通信量以更有效地使用服务器资源。
使用租约管理远程对象的生存期是引用计数的一种替代方法,引用计数在不可靠的网络连接上可能是复杂而低效的。虽然可以将租约配置为延长远程对象的生存期以超过所需的精确长度,但是由于减少了专用于引用计数和向客户端发送请求操作的网络通信量,因而使租约在为特定方案正确配置时成为一种很有吸引力的解决方案。
下表描述租约的主要属性。
属性 | 说明 |
---|---|
InitialLeaseTime |
指定对象在租约管理器开始执行删除对象的过程之前将保留在内存中的初始时间长度。在配置文件中,它是 <lifetime> 元素 配置元素的 leaseTime 属性。默认值为 5 分钟。租约时间为零则将租约设置为具有无限长的生存期。 |
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 设置为 full 的情况下才可能进行此 DOS 攻击。
租约被允许过期时,它不再接受任何其他租约消息或主办方返回的内容。租约的引用将从租约列表中移除,而且 .NET Framework 远程处理系统会将该对象引用从其内部表中移除。然后,垃圾回收系统将移除该租约和对象。
请参见
任务
如何:重写 InitializeLifetimeService 接口
如何:续订租约
参考
远程处理设置架构
ILease
RemotingServices.GetLifetimeService
MarshalByRefObject.InitializeLifetimeService