会员
周边
众包
新闻
博问
闪存
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式
...
退出登录
注册
登录
IT难民
Visual Studio 2005--- Developer EXpress 2005
博客园
首页
新随笔
管理
[Remoting专题系列] 四:生存期租约
Remoting 采取了一种称之为 "租约" 的机制来管理远程对象(Singleton、CAO)的生存期策略。每个应用程序域中都有一个租约管理器(LifetimeServices),它负责管理所有参与生存期的远程对象租约。租约管理器定期检查所有租约以确定过期的租约时间,如果租约已过期,将向该对象发起人(Sponsor)的发送请求,查询是否有谁要续订租约,若没有任何发起人续订该租约,租约将被移除,该远程对象也会被删除等待垃圾回收器回收。如果远程对象被发起人多次续订租约或被客户端持续调用,其生存期可以比其生存期租约长得多。 所谓发起人 (Sponsor,MSDN 翻译为"主办方",真别扭!) 就是一个或多个与远程对象关联,用于定义租约延长时间的对象。租约管理器通过回调发起人方法(ISponsor.Renewal)来查询是否续订租约。发起人需要继承自 MarshalByRefObject,且必须实现 ISponsor 接口。在 System.Runtime.Remoting.Lifetime 名字空间中,Framework 为我们提供了一个缺省实现 —— ClientSpo
Remoting 采取了一种称之为
"
租约
"
的机制来管理远程对象(Singleton、CAO)的生存期策略。每个应用程序域中都有一个租约管理器(LifetimeServices),它负责管理所有参与生存期的远程对象租约。租约管理器定期检查所有租约以确定过期的租约时间,如果租约已过期,将向该对象发起人(Sponsor)的发送请求,查询是否有谁要续订租约,若没有任何发起人续订该租约,租约将被移除,该远程对象也会被删除等待垃圾回收器回收。如果远程对象被发起人多次续订租约或被客户端持续调用,其生存期可以比其生存期租约长得多。
所谓发起人 (Sponsor,MSDN 翻译为
"
主办方
"
,真别扭
!
) 就是一个或多个与远程对象关联,用于定义租约延长时间的对象。租约管理器通过回调发起人方法(ISponsor.Renewal)来查询是否续订租约。发起人需要继承自 MarshalByRefObject,且必须实现 ISponsor 接口。在 System.Runtime.Remoting.Lifetime 名字空间中,Framework 为我们提供了一个缺省实现 —— ClientSponsor。
租约参数
当参与生存期管理的远程对象被创建后,其租约被设置为 LifetimeServices.LeaseTime 或 ILease.InitialLeaseTime。
我们可以通过 ILease.CurrentLeaseTime 来检查对象租约过期的剩余时间。
客户端调用远程对象方法时,会发生隐式续订租约行为。当 CurrentLeaseTime 小于 RenewOnCallTime,则租约被设置为 RenewOnCallTime。
租约管理器每隔一定时间(LeaseManagerPollTime)检查一次租约列表,如果某租约过期则通知其发起人,询问是否进行续订。如发起人未能在 SponsorshipTimeout 时间内响应,则移除该主办方并调用另一主办方。如果没有其他主办方,则租约过期,且垃圾回收器将处置该远程对象。
租约过期试验
using
System;
using
System.Collections;
using
System.Collections.Generic;
using
System.Reflection;
using
System.Threading;
using
System.Runtime.Serialization;
using
System.Runtime.Serialization.Formatters;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.CompilerServices;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
using
System.Runtime.Remoting.Messaging;
using
System.Runtime.Remoting.Lifetime;
namespace
Learn.Library.Remoting
{
public
class
RemotingTest2
{
/**/
///
<summary>
///
远程类型
///
</summary>
public
class
Data : MarshalByRefObject
{
private
Guid guid
=
Guid.NewGuid();
public
void
Test()
{
Console.WriteLine(
"
{0} in {1}
"
, guid, AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine((InitializeLifetimeService()
as
ILease).CurrentLeaseTime);
}
}
/**/
///
<summary>
///
服务器端代码
///
</summary>
static
void
Server()
{
//
创建新的应用程序域,以便模拟分布结构。
AppDomain server
=
AppDomain.CreateDomain(
"
server
"
);
server.DoCallBack(
delegate
{
//
设置缺省生存期
LifetimeServices.LeaseTime
=
TimeSpan.FromSeconds(
1
);
LifetimeServices.RenewOnCallTime
=
TimeSpan.FromSeconds(
1
);
LifetimeServices.LeaseManagerPollTime
=
TimeSpan.FromSeconds(
1
);
LifetimeServices.SponsorshipTimeout
=
TimeSpan.FromSeconds(
1
);
TcpServerChannel channel
=
new
TcpServerChannel(
801
);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof
(Data),
"
data
"
,
WellKnownObjectMode.Singleton);
}
);
}
/**/
///
<summary>
///
客户端代码
///
</summary>
static
void
Client()
{
TcpClientChannel channel
=
new
TcpClientChannel();
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownClientType(
typeof
(Data),
"
tcp://localhost:801/data
"
);
//
创建远程对象并调用其方法
for
(
int
i
=
0
; i
<
3
; i
++
)
{
Data data
=
new
Data();
data.Test();
Thread.Sleep(
5000
);
}
}
static
void
Main()
{
Server();
Client();
}
}
}
输出:
6ac6fcb9
-
6a5d
-
427b
-
92bb
-
cfdcb2265911
in
server
00
:
00
:
00.9899856
86a1716f
-
1ebd
-
47d2
-
af80
-
e501d20813b9
in
server
00
:
00
:
01
9a1039e0
-
fac7
-
4bbb
-
80c4
-
0bc7d5c9c2ff
in
server
00
:
00
:
01
通过输出结果,我们发现 Singleton MBR 对象过期后重新创建。
初始化租约
1
. 默认租约:用 LifetimeServices 设置所有对象的默认租约。
LifetimeServices.LeaseTime
=
TimeSpan.FromSeconds(
1
);
LifetimeServices.RenewOnCallTime
=
TimeSpan.FromSeconds(
1
);
LifetimeServices.LeaseManagerPollTime
=
TimeSpan.FromSeconds(
1
);
LifetimeServices.SponsorshipTimeout
=
TimeSpan.FromSeconds(
1
);
2
. 自定义租约:重写 MarshalByRefObject.InitializeLifetimeService() 自定义对象租约。当 ILease.CurrentState 属性为 LeaseState.Initial 时,可以设置租约的属性。一旦设置,就不能直接更改它们。
public
class
Data : MarshalByRefObject
{
public
override
object
InitializeLifetimeService()
{
ILease lease
=
(ILease)
base
.InitializeLifetimeService();
if
(lease.CurrentState
==
LeaseState.Initial)
{
lease.InitialLeaseTime
=
TimeSpan.FromSeconds(
1
);
lease.SponsorshipTimeout
=
TimeSpan.FromSeconds(
1
);
lease.RenewOnCallTime
=
TimeSpan.FromSeconds(
2
);
}
return
lease;
}
}
续订租约
续订租约的方式有:
隐式续订:在调用远程对象方法时发生。
显示续订:调用 ILease.Renew()。
发起租约:通过创建发起人(Sponsor)来延长租约。
在客户端调用 ILease.Renew() 显示续订租约,如果 CurrentLeaseTime 小于续订时间,则租约时间被设置为续订时间。
static
void
Client()
{
//
创建并注册信道
TcpClientChannel channel
=
new
TcpClientChannel();
ChannelServices.RegisterChannel(channel,
false
);
//
注册远程对象
RemotingConfiguration.RegisterWellKnownClientType(
typeof
(Data),
"
tcp://localhost:801/data
"
);
//
创建远程对象并调用其方法
Data data
=
new
Data();
(data.GetLifetimeService()
as
ILease).Renew(TimeSpan.FromSeconds(
100
));
}
posted on
2007-06-05 09:27
编程山人
阅读(
456
) 评论(
0
)
编辑
收藏
举报
会员力量,点亮园子希望
刷新页面
返回顶部