建设网站包维护,wordpress rss修改,西地那非片怎么服用最佳,教育类网站建设方案使用.NET Remoting开发分布式应用——基于租约的生存期一#xff0e;概述知名类型的SingleCall对象可以在客户程序的方法调用之后被垃圾收集器清理掉#xff0c;因为它没有保持状态#xff0c;属于无状态的。而客户激活的类型的对象和知名类型的SingleTon对象都属于生存期长…使用.NET Remoting开发分布式应用——基于租约的生存期一概述 知名类型的SingleCall对象可以在客户程序的方法调用之后被垃圾收集器清理掉因为它没有保持状态属于无状态的。而客户激活的类型的对象和知名类型的SingleTon对象都属于生存期长的对象如果在客户程序停止使用远程对象之前远程对象被禁用了则客户程序会得到一个RemotingException异常。因为该对象已经和下一个方法调用从客户程序进行的方法调用断开了连接只要客户程序需要该对象它就必须被激活。 微软的DCOM技术使用了Ping机制在这种机制下客户程序有规律的对服务程序发出Ping请求以通知服务程序自己仍旧活着并通知服务程序自己需要使用哪个对象。.NET Remoting使用的是基于租约的生存期机制在租约期内对象一直存活着直到租借时间结束.NET Remoting使用Leasing程序完成了这项工作。 .NET Remoting允许我们通过一些方式来修改对象的租约时间一种方式是编写程序代码来完成另外一种方式是使用配置文件有关配置文件的介绍可以参见《使用.NET Remoting开发分布式应用——配置文件篇》的内容还有一种方式是通过发起人Sponsor来配置租约。先来看一下租约配置选项的默认值 租约配置 默认值秒 LeaseTime 300 RenewOnCallTime 120 SponsorshipTimeout 120 LeaseManagerPollTime 10 使用LeaseTime选项可以定义远程对象的最长租借时间。如果客户程序一段时期内不再需要远程对象了那么该对象将被禁用。每次客户程序使用远程对象调用方法时RenewOnCallTime定义的一个值会递增租借时间。SponsorshipTimeout选项定义了在调用结束之前的那段默认时间而LeaseManagerPollTime定义了发起人必须返回延长的那部分租借时间。 租约可以实现 ILease 接口并存储一个属性集合用于确定更新的策略和方法。您也可以使用调用来更新租约。每次调用远程对象上的方法时租约时间都会设置为目前 LeaseTime 最大值加上 RenewOnCallTime。LeaseTime 即将过期时发起者会被要求更新租约。因为我们有时会遇上网络不稳定所以可能会找不到租约发起者。为了确保不在服务器上留下无效对象每个租约都带有一个 SponsorshipTimeout。该值指定了租约终止之前等待租约发起者回复的时间长度。如果 SponsershipTimeout 为零CurrentLeaseTime 会被用于确定租约的过期时间。如果 CurrentLeaseTime 的值为零则租约不会过期。配置或 API 可用于替代 InitialLeaseTime、SponsorshipTimeout 和 RenewOnCallTime 的默认值。 租约管理器维护着一个按发起时间从大到小存储的发起者列表它们实现 ISponsor 接口。需要调用发起者以更新租约时间时租约管理器会从列表的顶部开始向一个或多个发起者要求更新租约时间。列表顶部的发起者表示其以前请求的租约更新时间最长。如果发起者没有在 SponsorshipTimeOut 时间段内响应则它会被从列表中删除。通过调用 GetLifetimeService 并将对象租约作为参数即可以获得该对象租约。该调用是 RemotingServices 类的一个静态方法。如果对象在应用程序域内部则该调用的参数是对象的本地引用且返回的租约也是该租约的本地引用。如果对象是远程的则代理会作为一个参数传递且返回给调用方的是租约的透明代理。 二通过配置文件配置租约 在服务器上的应用程序配置文件中编写生存期的配置。在这种方式下生存期配置对整个应用程序都有效。在应用程序配置文件的lifttime标记中可以通过修改特性的方式来配置。 示例代码 1?xml version1.0 encodingutf-8 ? 2configuration 3 system.runtime.remoting 4 application 5 service 6 wellknown 7 modeSingleton 8 typeRemotingSamples.HelloServer, General 9 objectUriSayHello /10 /service11 channels12 channel port8086 refhttp/13 /channels14 15 lifetime 16 leaseTime7M 17 sponsorshipTimeout7M 18 renewOnCallTime7M19 leaseManagerPollTime7S20 /21 /application22 /system.runtime.remoting23/configuration24 三编写代码配置租约 如果我们需要一些带有不同的生存期要求的远程对象那么最好是通过编程的方式来为对象设置生存期。在远程对象中可以覆盖InitializeLifetimeService()方法。基类MarshalByRefObject中的InitializeLifetimeService()方法会返回一个对Ilease接口该接口可用于修改默认值的引用因为只有在租约没有生效的时候才可能修改默认值所以我们需要检查租约的当前状态并把它和枚举值LeaseState.Initial进行比较。 示例代码 1 public override Object InitializeLifetimeService() 2 { 3 4 ILease lease (ILease)base.InitializeLifetimeService(); 5 // Normally, the initial lease time would be much longer. 6 // It is shortened here for demonstration purposes. 7 if (lease.CurrentState LeaseState.Initial) 8 { 9 lease.InitialLeaseTime TimeSpan.FromSeconds(3);10 lease.SponsorshipTimeout TimeSpan.FromSeconds(10);11 lease.RenewOnCallTime TimeSpan.FromSeconds(2);12 }13 return lease;14 } 租约的状态LeaseState枚举值如下表所示 租约状态的枚举值 说明 Active 指明租约处于激活状态 Expired 表明租约已经期满不能再恢复。当租约管理器发现对象上的租约已经期满它将联系处于发起人列表中的租约发起人决定是否恢复它的租约。如果发起人的响应超时它将尝试联系发起人列表中的下一个发起人。如果租约管理器不能成功的从任何一个发起人那里获得一个租约恢复响应它将租约对象设置为Expired状态。一旦如此租约对象就不能再复活只能被垃圾收集器收集 Initial 表明租约还没有被创建但仍然没有被激活 Null 租约还没有被初始化 Renewing 表明租约已经期满租约管理器正在寻找发起人。这个状态指出租约管理器正在尝试联系已经为这个对象的租约恢复而注册的租约发起人 只有当租约处于初始状态时才可以更改租约属性。InitializeLifetimeService 的实现通常调用基类的相应方法来检索远程对象的现有租约。如果在此之前从未对该对象封送过则返回的租约会处于其初始状态且可以设置租约属性。一旦封送了对象则租约会从初始状态变为激活状态并忽略任何初始化租约属性的尝试但有一种情况例外。激活远程对象时将调用 InitializeLifetimeService。通过激活调用可以提供一个租约发起者的列表而且当租约处于激活状态时可以随时将其他发起者添加到列表中。 可以下列方式延长租约时间 客户端可以调用 Lease 类上的 Renew 方法。 租约可以向某个发起者请求 Renewal。 当客户端调用对象上的某个方法时RenewOnCall 值会自动更新租约。 一旦租约过期其内部状态会由 Active 变为 Expired且不再对发起者进行任何调用对象也会被作为垃圾回收。一般情况下如果发起者分散在 Web 上或位于某个防火墙的后面远程对象回叫发起者时会遇到困难。因此发起者不必与客户端处于同一位置只要远程对象能够访问得到它可以为网络上的任意位置。 四通过发起者来配置租约 我们也可以通过发起者来修改生存期服务数值。通过发起者配置.NET Remoting运行时使用ISponsor接口来延长远程对象的生存期ISponsor定义了Renewal()方法.NET Remoting的基础结构会调用该方法来延长当前对象的租借时间。使用租约参数可以读取当前租约的配置和租借时间的实际情况。我们必须使用返回值为对象定义额外的租借时间。在下面的示例代码中创建了一个发起者并修改它的相关的配置参数。 示例代码 1using System; 2using System.Runtime.Remoting; 3using System.Runtime.Remoting.Channels; 4using System.Runtime.Remoting.Channels.Tcp; 5using System.Runtime.Remoting.Channels.Http; 6using System.Runtime.Remoting.Activation; 7using System.Runtime.Remoting.Lifetime; 8using System.IO; 910namespace RemotingSamples 11{12 public class Client13 {14 public static void Main(string[] args)15 {16 //使用TCP通道得到远程对象17 ChannelServices.RegisterChannel(new HttpChannel());1819 HelloServer obj (HelloServer)Activator.GetObject(20 typeof(RemotingSamples.HelloServer),21 http://localhost:8086/SayHello);22 if (obj null)23 {24 System.Console.WriteLine(25 Could not locate HTTP server);26 }27 2829 MySponsor sponsor new MySponsor();30 sponsor.RenewalTime TimeSpan.FromMinutes(2);31 sponsor.Register(obj);3233 ILease lease (ILease)obj.GetLifetimeService();34 if (lease ! null)35 {36 Console.WriteLine(Lease Configuration:);37 Console.WriteLine(InitialLeaseTime: 38 lease.InitialLeaseTime);39 Console.WriteLine(RenewOnCallTime: 40 lease.RenewOnCallTime);41 Console.WriteLine(SponsorshipTimeout: 42 lease.SponsorshipTimeout);43 Console.WriteLine(lease.CurrentLeaseTime);44 }4546 }4748 }4950 public class MySponsor:ClientSponsor,ISponsor51 {52 TimeSpan ISponsor.Renewal(ILease lease)53 {54 Console.WriteLine(Renewal called);5556 return this.RenewalTime;57 }58 }59}60 五总结 通过租约来管理远程对象的生存期可以作为引用计数的一种替代方法因为当网络连接的性能不可靠时引用计数会显得复杂和低效。尽管有人会坚持认为远程对象的生存期比所需的时间要长但与引用计数和连接客户相比租约降低了网络的繁忙程度将会成为一种非常受欢迎的解决方案。 附录一个完整的用程序代码配置租约生存期的例子 Server.cs 1using System; 2using System.Runtime.Remoting; 3using System.Runtime.Remoting.Channels; 4using System.Runtime.Remoting.Channels.Tcp; 5using System.Runtime.Remoting.Channels.Http; 6 7namespace RemotingSamples 8{ 910 public class Server11 {12 public static int Main(string [] args) 13 {141516 TcpChannel chan1 new TcpChannel(8085);17 HttpChannel chan2 new HttpChannel(8086);1819 ChannelServices.RegisterChannel(chan1);20 ChannelServices.RegisterChannel(chan2);2122 //服务器端激活。23 RemotingConfiguration.RegisterWellKnownServiceType24 (25 typeof(HelloServer),26 SayHello,27 WellKnownObjectMode.Singleton28 ); 2930 System.Console.WriteLine(Press Enter key to exit);31 System.Console.ReadLine();32 return 0;33 }3435 }36}37 HelloWord.cs 1using System; 2using System.Collections.Generic; 3using System.Text; 4using System.Runtime.Remoting.Lifetime; 5 6namespace RemotingSamples 7{ 8 public class HelloServer : MarshalByRefObject 9 {10 public HelloServer()11 {12 Console.WriteLine(HelloServer activated);13 }14 public String HelloMethod(String name)15 {16 Console.WriteLine(17 Server Hello.HelloMethod : {0}, name);18 return Hi there name;19 }2021 // Overrides the lease settings for this object.22 public override object InitializeLifetimeService()23 {2425 ILease lease (ILease)base.InitializeLifetimeService();26 // Normally, the initial lease time would be much longer.27 // It is shortened here for demonstration purposes.28 if (lease.CurrentState LeaseState.Initial)29 {30 lease.InitialLeaseTime TimeSpan.FromSeconds(3);31 lease.SponsorshipTimeout TimeSpan.FromSeconds(10);32 lease.RenewOnCallTime TimeSpan.FromSeconds(2);33 }34 return lease;35 }3637 }38}3940 414243 Client.cs 1using System; 2using System.Runtime.Remoting; 3using System.Runtime.Remoting.Channels; 4using System.Runtime.Remoting.Channels.Tcp; 5using System.Runtime.Remoting.Channels.Http; 6using System.Runtime.Remoting.Activation; 7using System.Runtime.Remoting.Lifetime; 8using System.IO; 910namespace RemotingSamples 11{12 public class Client13 {14 public static void Main(string[] args)15 {16 //使用TCP通道得到远程对象17 ChannelServices.RegisterChannel(new HttpChannel());1819 HelloServer obj (HelloServer)Activator.GetObject(20 typeof(RemotingSamples.HelloServer),21 http://localhost:8086/SayHello);22 if (obj null)23 {24 System.Console.WriteLine(25 Could not locate HTTP server);26 }27 2829 ILease lease (ILease)obj.GetLifetimeService();30 if (lease ! null)31 {32 Console.WriteLine(Lease Configuration:);33 Console.WriteLine(InitialLeaseTime: 34 lease.InitialLeaseTime);35 Console.WriteLine(RenewOnCallTime: 36 lease.RenewOnCallTime);37 Console.WriteLine(SponsorshipTimeout: 38 lease.SponsorshipTimeout);39 Console.WriteLine(lease.CurrentLeaseTime);40 }4142 }4344 }4546}47