前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Remoting 体系结构 之 生命周期管理

.NET Remoting 体系结构 之 生命周期管理

作者头像
DougWang
发布2020-02-17 17:35:10
6040
发布2020-02-17 17:35:10
举报
文章被收录于专栏:java跬步java跬步

客户端和服务器怎样检测到另一端是否可用?此时,我们遇到的问题是什么呢?

对于客户端,答案比较简单。只要客户端调用远程对象上的方法,就会产生一个 System.Runtime.Remoting.RemotingException 类型的异常。此时,只需处理这个异常,完成一些必要 的工作,如重试、写日志以及通知用户等。 对于服务器,服务器应何时检测客户端是否还在?即服务器何时可以清理为该客户端保存的资 源?可以一直等待来自客户端的下一个方法调用,但该客户端可能再没有方法调用了。在 COM 领 域中,DCOM 协议使用 ping 机制解决这个问题。客户端把 ping 和引用对象的信息发送给服务器。 因为客户端在服务器上可能有几百个引用的对象,所以 ping 中的信息非常多。为了使这个机制更加 有效,DCOM 不发送所有对象的所有信息,而只发送与上一个 ping 不同的信息。 虽然这个 ping 机制在 LAN 上非常有效,但它并不适用于可伸缩的解决方案。考虑到有成千上 万的客户端向服务器发送 ping 信息,.NET Remoting 为生命周期管理提供了一个伸缩性更强的解决 方案:即租约分布式垃圾收集器(Leasing Distributed Garbage Collector,LDGC)。 这个生命周期管理只对客户端激活的对象和知名的单一对象有效。因为单一对象不保存状态, 所以在每个方法调用之后就可以销毁它们。客户端激活的对象保存状态,我们应该知道它们使用的 资源。如果在应用程序域外部引用客户端激活的对象,就需要创建租约。租约有一个租约时间。当 租约时间为 0时,租约就已经到期,此时远程对象就会断开连接,后由垃圾收集器回收。

1. 租约的续约 当租约到期之后,如果客户端还调用对象上的方法,就会抛出异常。如果有一个客户端,其中 需要租约远程对象的时间超过了 300 秒(默认的租约时间)时,那么有以下 3 种方法进行续约:

●  隐式续约 —— 当客户端调用远程对象上的方法时,租约的隐式续约会自动进行。如果当前 租约时间小于 RenewOnCallTime 的值,租约时间就设置为 RenewOnCallTime。 ●  显式续约 —— 通过显式续约,客户端可以指定新的租约时间,这项工作可以通过 ILease 接口 的Renew()方法完成。通过调用透明代理的 GetLifetimeService()方法,就可以使用 ILease 接口。

●  发起租约 —— 这是第三种续约的方法。客户端可以创建一个实现 ISponsor 接口的发起者, 并使用 ILease 接口的 Register()方法在租约服务中注册这个发起者。发起者定义租约延长的 时间。当租约到期时,发起者就要求延长租约时间。如果要长期租约服务器上的远程对象, 就可以使用这个发起租约机制。

2. 租约的配置值 可以配置下面的一些值:

●  LeaseTime ——它定义租约到期之前的时间。

●  RenewOnCallTime ——这个时间是租约在方法调用上设置的时间,它指的是续约时间,如 果当前租约时间的值低于这个时间,就要进行续约

●  SponsorshipTimeout —— 如果 SponsorshipTimeout 中没有租约发起者,远程基础结构就会 寻找下一个发起者。如果没有更多发起者,租约就到期。

●  LeaseManagerPollTime —— 租约管理器隔一段时间就检查一次,查看有没有对象到期, LeaseManagerPollTime 定义这个时间间隔。

3. 管理生命周期所使用的类

ClientSponsor 类实现 ISponsor 接口。在客户端可以使用它延长租约时间。使用 ILease 接口,可以 获取租约的所有信息、所有租约属性,以及当前租约的时间和状态。通过 LeaseState 枚举类型指定状 态。通过 LifetimeServices 实用程序类,可以为应用程序域中所有远程对象的租约设置或获取属性。

4. 获取租约信息示例

在这个小示例代码中,调用透明代理的 GetLifetimeService()方法访问租约信息。对于 ILease 接 口,必须声明 System.Runtime.Remoting.Lifetime 名称空间。对于 UrlAttribute 类,必须导入 System.Runtime.Remoting.Activation 名称空间。 租约机制只能用于有状态的(客户端激活的和单一)对象。由于每次调用方法时都实例化单一调 用对象,因此租约机制不适用于单一调用对象。为了通过服务器提供客户端激活的对象,可以把远 程处理配置更改为调用 RegisterActivatedServiceType()方法:

RemotingConfiguration.ApplicationName = "Hello"; 
RemotingConfiguration.RegisterActivatedServiceType(typeof(Hello)); 

 在客户端应用程序中,远程对象的实例化也必须更改。在此,并不使用 Activator.GetOnject()方 法,而是使用 Activator.CreateInstance()方法调用客户端激活的对象:

ChannelServices.RegisterChannel(new TcpClientChannel(), true); 
object[] attrs = {new UrlAttribute("tcp://localhost:8086/Hi") };
 Hello obj = (Hello)Activator.CreateInstance(typeof(Hello), null, attrs); 

为了显示租约时间,可以调用代理对象中的 GetLifetimeService()方法使用返回的 ILease 接口.

使用 System.Runtime.Remoting.Lifetime.LifetimeServices 实用程序类,服务器自身就可以为所有 远程对象更改默认的租约配置: LifetimeServices.LeaseTime = TimeSpan.FromMinutes(10);

LifetimeServices.RenewOnCallTime = TimeSpan.FromMinutes(2); 如果希望不同的默认生命周期依赖于远程对象的类型,则可以重写 MarshalByRefObject 基类的 InitializeLifetimeService()方法,更改远程对象的租约配置: public class Hello : System.MarshalByRefObject {

public override Object InitializeLifetimeService()

{

ILease lease = (ILease)base.InitializeLifetimeService();

lease.InitialLeaseTime = TimeSpan.FromMinutes(10);

lease.RenewOnCallTime = TimeSpan.FromSeconds(40);

return lease;

} 使用后面讨论的配置文件,也可以完成生命周期服务的配置。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2013-02-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档