.Net Remoting体系架构
---------------------------------------------.Net Remoting体系架构---------------------------------
•Remoting边界
•可远程化的对象类型
•跨越Remoting边界通信
–用ObjRef列集对象引用
–客户端的代理
–消息机制
–通道
•对象激活与其生命租用
------------------------------------------------------------------------------------------------------------
Remoting边界:
进程
Windows操作系统把Application分隔在单独的进程里
应用程序域
Win32进程可容纳多个应用程序域
上下文
CLR将应用程序域划分为多个上下文
![](/images/cnblogs_com/jigee/remoting.jpg)
可远程化的对象类型:
不是所有对象都能跨越Remoting边界被外部访问调用
可远程化的对象类型
By Value
传递对象副本(类似于文件的拷贝)
By Ref
传递对象引用(类似于文件的快捷方式)
Context Bound
即使是在同一个Domain里,但如果是在不同的Context中,也需要按引用列集后才能访问
![](/images/cnblogs_com/jigee/value.jpg)
![](/images/cnblogs_com/jigee/ref2.jpg)
跨越Remoting边界通信:
用ObjRef列集对象引用
服务器端:
1.创建用以描述远程对象类型的ObjRef实例
2.序列化该ObjRef实例为数据流
3.传输该数据流
客户端:
1.接收到数据流
2.将该数据流反序列化为一个ObjRef实例
3.根据该ObjRef实例的描述信息,创建代理对象
ObjRef包含的描述信息:
1.URI
-服务器端激活的:发布的URI
-客户端激活的:.Net Remoting会生成GUID
2.MetaData
-class、assembly信息
-所实现的接口及其派生层次信息
3.通道信息
-识别Context,Domain,Process的信息
-识别传输类型,IP地址以及端口号等信息
客户端的Proxy
TransparentProxy ---- _TransparentProxy
将方法的调用转化为消息对象,并将该消息转给后面的RealProxy
RealProxy ---- RemotingProxy
接收调用的消息对象并交给.Net Remoting Infrastructure,用以传给最终的远程对象
![](/images/cnblogs_com/jigee/procy.jpg)
消息机制
计算机中方法的调用:
将参数,返回地址压入栈
将运行指令指针指向方法入口地址
按规则将参数,返回地址弹出栈
计算结果并写到返回地址处
总结:堆栈起到了方法调用之间通信传输层的作用,在调用和被调用方之间传递方法参数并返回结果。
抽象与模型化传统的方法的调用:
将方法调用的相关信息封装在一个消息对象中,包括方法调用,输入/出参数,构造函数的调用,方法返回值,异常等等。
在.Net Remoting中定义了IMessage接口,其中包含了一个名为Properties,类型为IDictionary的属性成员,用来保存方法调用的信息。
.Net Remoting通过TP/RP来获取方法调用的消息对象:
1. TP通过Unmanaged代码截获调用方进行的类似调用本地对象方法的调用,
2. TP构建一个结构MessageData,里面包含一些指向Unmanaged内存空间的地址,用这些信息来描述该方法的调用。
3. TP将该结构传给RP的Private1Invoke方法RP的Private1Invoke方法会根据MessgeData来创建一个IMessage的消息对象实例,
4. RP将消息对象实例通过一系列的消息接受链(MessageSink)传递到远程端。
5. 在远端的消息接受链末端是一个Stackbuilder接受器,它会把IMessage对象实例反向还原成原始底层的方法调用的堆栈信息
6. 根据堆栈信息进行远程端机器上的方法调用
7. Stackbuilder接受器将调用的返回打包为RetunMessage(实现了IMessage )的消息对象实例 ,然后沿原路传回到调用端的代理对象内。
上下文与通道:
特使接收器链
上下文接收器链
交叉上下文通道
通往远程(其他Domain)的通道接受器链
![](/images/cnblogs_com/jigee/relation.jpg)
对象激活与其生命租用:
对象激活方式
服务器端激活
Singleton
SingleCall
客户端激活
![](/images/cnblogs_com/jigee/Singleton.jpg)
![](/images/cnblogs_com/jigee/call.jpg)
生命租用周期
非租用的生命周期管理方案
Ping:确保客户仍处于活动连接状态
引用计数器:表示连接客户的数目
存在的问题:ping所引起的网络流量对整体运行产生不良影响
生命租用周期
基于租用的生存周期管理方案
租用
租用管理器
发起者
租用
InitializeLifetimeServices来获得租用
租用:ILease的实现
InitialLeaseTime: 初始化有效时间,默认值为300秒,如果为0,表示永不过期;
CurrentLeaseTime:当前租用时间,首次获得租用时,为InitialLeaseTime的值 ;
RenewOnCallTime: 调用远程对象一个方法时的租用更新时间,默认值为120秒;
SponsorshipTimeout: 超时值,通知Sponsor(发起人)租用过期后,Remoting会等待的时间,默认值为120秒;
Register
租用管理器
添加租用:
内部维护一个Hashtable,将到期时间和租用对应起来
管理租用:
定时(默认每10s, LifetimeService.LeaseManagerPollTime来设置)检查Hashtable中的时间,找到每个已过期的租用,要求它们去让它们的发起者来做更新
释放租用:
如果租用过期且没能做更新,那么租用管理器会:
1. 将该租用状态设为LeaseState.Expired;
2. 将该租用从内部的Hashtable中删除;
3. 断开该租用对象所关联的远程对象与.Net Remoting 的Infrastructure的连接
4. 断开该租用对象与.Net Remoting Infrastructure的连接此时该租用及其关联的远程对象都不再被引用,两者都将准备着被GC回收掉
发起者可为远程对象更新租用的对象,实现ISponsor接口,且继承自MarshalByRefObject;通过ILease.Register将一个发起者注册到一个租用上;.Net Framework定义了一个现成的实现了ISponsor接口的ClientSponsor类.
------------------------------------------------------------------------------------------------------------
Remoting边界:
进程
Windows操作系统把Application分隔在单独的进程里
应用程序域
Win32进程可容纳多个应用程序域
上下文
CLR将应用程序域划分为多个上下文
![](/images/cnblogs_com/jigee/remoting.jpg)
可远程化的对象类型:
不是所有对象都能跨越Remoting边界被外部访问调用
可远程化的对象类型
By Value
传递对象副本(类似于文件的拷贝)
By Ref
传递对象引用(类似于文件的快捷方式)
Context Bound
即使是在同一个Domain里,但如果是在不同的Context中,也需要按引用列集后才能访问
![](/images/cnblogs_com/jigee/value.jpg)
![](/images/cnblogs_com/jigee/ref2.jpg)
跨越Remoting边界通信:
用ObjRef列集对象引用
服务器端:
1.创建用以描述远程对象类型的ObjRef实例
2.序列化该ObjRef实例为数据流
3.传输该数据流
客户端:
1.接收到数据流
2.将该数据流反序列化为一个ObjRef实例
3.根据该ObjRef实例的描述信息,创建代理对象
ObjRef包含的描述信息:
1.URI
-服务器端激活的:发布的URI
-客户端激活的:.Net Remoting会生成GUID
2.MetaData
-class、assembly信息
-所实现的接口及其派生层次信息
3.通道信息
-识别Context,Domain,Process的信息
-识别传输类型,IP地址以及端口号等信息
客户端的Proxy
TransparentProxy ---- _TransparentProxy
将方法的调用转化为消息对象,并将该消息转给后面的RealProxy
RealProxy ---- RemotingProxy
接收调用的消息对象并交给.Net Remoting Infrastructure,用以传给最终的远程对象
![](/images/cnblogs_com/jigee/procy.jpg)
消息机制
计算机中方法的调用:
将参数,返回地址压入栈
将运行指令指针指向方法入口地址
按规则将参数,返回地址弹出栈
计算结果并写到返回地址处
总结:堆栈起到了方法调用之间通信传输层的作用,在调用和被调用方之间传递方法参数并返回结果。
抽象与模型化传统的方法的调用:
将方法调用的相关信息封装在一个消息对象中,包括方法调用,输入/出参数,构造函数的调用,方法返回值,异常等等。
在.Net Remoting中定义了IMessage接口,其中包含了一个名为Properties,类型为IDictionary的属性成员,用来保存方法调用的信息。
.Net Remoting通过TP/RP来获取方法调用的消息对象:
1. TP通过Unmanaged代码截获调用方进行的类似调用本地对象方法的调用,
2. TP构建一个结构MessageData,里面包含一些指向Unmanaged内存空间的地址,用这些信息来描述该方法的调用。
3. TP将该结构传给RP的Private1Invoke方法RP的Private1Invoke方法会根据MessgeData来创建一个IMessage的消息对象实例,
4. RP将消息对象实例通过一系列的消息接受链(MessageSink)传递到远程端。
5. 在远端的消息接受链末端是一个Stackbuilder接受器,它会把IMessage对象实例反向还原成原始底层的方法调用的堆栈信息
6. 根据堆栈信息进行远程端机器上的方法调用
7. Stackbuilder接受器将调用的返回打包为RetunMessage(实现了IMessage )的消息对象实例 ,然后沿原路传回到调用端的代理对象内。
上下文与通道:
特使接收器链
上下文接收器链
交叉上下文通道
通往远程(其他Domain)的通道接受器链
![](/images/cnblogs_com/jigee/relation.jpg)
对象激活与其生命租用:
对象激活方式
服务器端激活
Singleton
SingleCall
客户端激活
![](/images/cnblogs_com/jigee/Singleton.jpg)
![](/images/cnblogs_com/jigee/call.jpg)
生命租用周期
非租用的生命周期管理方案
Ping:确保客户仍处于活动连接状态
引用计数器:表示连接客户的数目
存在的问题:ping所引起的网络流量对整体运行产生不良影响
生命租用周期
基于租用的生存周期管理方案
租用
租用管理器
发起者
租用
InitializeLifetimeServices来获得租用
租用:ILease的实现
InitialLeaseTime: 初始化有效时间,默认值为300秒,如果为0,表示永不过期;
CurrentLeaseTime:当前租用时间,首次获得租用时,为InitialLeaseTime的值 ;
RenewOnCallTime: 调用远程对象一个方法时的租用更新时间,默认值为120秒;
SponsorshipTimeout: 超时值,通知Sponsor(发起人)租用过期后,Remoting会等待的时间,默认值为120秒;
Register
租用管理器
添加租用:
内部维护一个Hashtable,将到期时间和租用对应起来
管理租用:
定时(默认每10s, LifetimeService.LeaseManagerPollTime来设置)检查Hashtable中的时间,找到每个已过期的租用,要求它们去让它们的发起者来做更新
释放租用:
如果租用过期且没能做更新,那么租用管理器会:
1. 将该租用状态设为LeaseState.Expired;
2. 将该租用从内部的Hashtable中删除;
3. 断开该租用对象所关联的远程对象与.Net Remoting 的Infrastructure的连接
4. 断开该租用对象与.Net Remoting Infrastructure的连接此时该租用及其关联的远程对象都不再被引用,两者都将准备着被GC回收掉
发起者可为远程对象更新租用的对象,实现ISponsor接口,且继承自MarshalByRefObject;通过ILease.Register将一个发起者注册到一个租用上;.Net Framework定义了一个现成的实现了ISponsor接口的ClientSponsor类.