首先说一下对租约的理解,租约就是服务端保留激活的对象的实例的一个时间,如果在这段时间里一直没有访问,那么租约分布式垃圾回收器就将销毁这个实例。这里指服务器端singleton和客户端激活两种方式激活的对象。为了让这个对象存在,我们就需要续约,续约有三种方法:
1 隐式续约,就是访问对象的方法,即可实现续约
2 显式续约,使用ILease.Renew(),不调用任何方法就可续约
3 发起租约,上面两种方式是由客户端自己来实现的,而发起租约是由一个发起者来实现续约,通过ILease.Register方法将租约注册,让发起者来续约。
租约的配置主要有四个属性
1 InitialLeaseTime 它表示激活一个对象之后,不再访问该对象的方法时,服务端保留该对象的最长时间。它为0时表示永远不过期。
2 RenewOnCallTime 它表示当客户端调用远程对象的方法时,服务端确定租约还剩下多长时间,如果时间RenewOnCallTime,便根据RenewOnCallTime的值更新租约。
3 SponsorshipTimeout 它表示的是当租约过期后并不是立即撤销该对象而还等待的时间。
4 CurrentLeaseTime表示当前租约的剩余时间。
下面用一个例子来说明
下面是解决方案的视图
client.cs
using
System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Lifetime;
using System.IO;
namespace RemotingSamples
{
public class Client
{
public static void Main(string[] args)
{
//使用TCP通道得到远程对象
ChannelServices.RegisterChannel(new TcpChannel());
HelloServer obj = (HelloServer)Activator.GetObject(
typeof(RemotingSamples.HelloServer),
"tcp://localhost:8085/SayHello");
if (obj == null)
{
System.Console.WriteLine(
"Could not locate TCP server");
}
//object[] attrs = { new UrlAttribute("tcp://localhost:8085/Hello") };
//HelloServer obj = (HelloServer)Activator.CreateInstance(typeof(HelloServer), null, attrs);
ILease lease = (ILease)obj.GetLifetimeService();
if (lease != null)
{
Console.WriteLine("Lease Configuration:");
Console.WriteLine("InitialLeaseTime: " +
lease.InitialLeaseTime);
Console.WriteLine("RenewOnCallTime: " +
lease.RenewOnCallTime);
Console.WriteLine("SponsorshipTimeout: " +
lease.SponsorshipTimeout);
Console.WriteLine(lease.CurrentLeaseTime);
}
}
}
}
client.exe.config
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Lifetime;
using System.IO;
namespace RemotingSamples
{
public class Client
{
public static void Main(string[] args)
{
//使用TCP通道得到远程对象
ChannelServices.RegisterChannel(new TcpChannel());
HelloServer obj = (HelloServer)Activator.GetObject(
typeof(RemotingSamples.HelloServer),
"tcp://localhost:8085/SayHello");
if (obj == null)
{
System.Console.WriteLine(
"Could not locate TCP server");
}
//object[] attrs = { new UrlAttribute("tcp://localhost:8085/Hello") };
//HelloServer obj = (HelloServer)Activator.CreateInstance(typeof(HelloServer), null, attrs);
ILease lease = (ILease)obj.GetLifetimeService();
if (lease != null)
{
Console.WriteLine("Lease Configuration:");
Console.WriteLine("InitialLeaseTime: " +
lease.InitialLeaseTime);
Console.WriteLine("RenewOnCallTime: " +
lease.RenewOnCallTime);
Console.WriteLine("SponsorshipTimeout: " +
lease.SponsorshipTimeout);
Console.WriteLine(lease.CurrentLeaseTime);
}
}
}
}
<
configuration
>
< system.runtime.remoting >
< application >
< client >
< wellknown type = " HelloServer, General " url = " http://localhost:8086/SayHello " />
</ client >
< channels >
< channel ref = " http " port = " 0 " ></ channel >
</ channels >
</ application >
</ system.runtime.remoting >
</ configuration >
HelloServer.cs
< system.runtime.remoting >
< application >
< client >
< wellknown type = " HelloServer, General " url = " http://localhost:8086/SayHello " />
</ client >
< channels >
< channel ref = " http " port = " 0 " ></ channel >
</ channels >
</ application >
</ system.runtime.remoting >
</ configuration >
using
System;
using System.Collections.Generic;
using System.Text;
namespace RemotingSamples
{
public class HelloServer : MarshalByRefObject
{
public HelloServer()
{
Console.WriteLine("HelloServer activated");
}
public String HelloMethod(String name)
{
Console.WriteLine(
"Server Hello.HelloMethod : {0}", name);
return "Hi there " + name;
}
}
}
server.cs
using System.Collections.Generic;
using System.Text;
namespace RemotingSamples
{
public class HelloServer : MarshalByRefObject
{
public HelloServer()
{
Console.WriteLine("HelloServer activated");
}
public String HelloMethod(String name)
{
Console.WriteLine(
"Server Hello.HelloMethod : {0}", name);
return "Hi there " + name;
}
}
}
using
System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
namespace RemotingSamples
{
public class Server
{
public static int Main(string [] args)
{
TcpChannel chan1 = new TcpChannel(8085);
HttpChannel chan2 = new HttpChannel(8086);
ChannelServices.RegisterChannel(chan1);
ChannelServices.RegisterChannel(chan2);
//服务器端激活。
RemotingConfiguration.RegisterWellKnownServiceType
(
typeof(HelloServer),
"SayHello",
WellKnownObjectMode.Singleton
);
//客户端激活
//RemotingConfiguration.ApplicationName = "Hello";
//RemotingConfiguration.RegisterActivatedServiceType(
// typeof(HelloServer));
System.Console.WriteLine("Press Enter key to exit");
System.Console.ReadLine();
return 0;
}
}
}
运行后服务器端会显示HelloServer activated,如果在五分钟内重新运行客户端,服务器端不会有变化,因为是Singleton激活方式,只有一个实例,但是如果五分钟后在运行一个客户端,服务器端会再次出现HelloServer activated,因为上一个对象实例已经被撤销,这是再次激活了一个新实例。
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
namespace RemotingSamples
{
public class Server
{
public static int Main(string [] args)
{
TcpChannel chan1 = new TcpChannel(8085);
HttpChannel chan2 = new HttpChannel(8086);
ChannelServices.RegisterChannel(chan1);
ChannelServices.RegisterChannel(chan2);
//服务器端激活。
RemotingConfiguration.RegisterWellKnownServiceType
(
typeof(HelloServer),
"SayHello",
WellKnownObjectMode.Singleton
);
//客户端激活
//RemotingConfiguration.ApplicationName = "Hello";
//RemotingConfiguration.RegisterActivatedServiceType(
// typeof(HelloServer));
System.Console.WriteLine("Press Enter key to exit");
System.Console.ReadLine();
return 0;
}
}
}
最后我们在介绍一下如何更改租约时间,主要有两种方法:
1 代码
在helloserver中加入一个Object InitializeLifetimeService()的重写来实现租约的更改
public
override
Object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
// Normally, the initial lease time would be much longer.
// It is shortened here for demonstration purposes.
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromSeconds(0);
lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}
2 配置文件
{
ILease lease = (ILease)base.InitializeLifetimeService();
// Normally, the initial lease time would be much longer.
// It is shortened here for demonstration purposes.
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromSeconds(0);
lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}
在配置文件中加入<lifetime
leaseTime="7M"
sponsorshipTimeout="7M"
renewOnCallTime="7M"
/>
来实现租约的更改