• .NET Remoting开发系列:(二) 对象生存周期管理


     本次议题  对象生存周期管理

       对于服务器对象不保留任何状态的SingleCall对象是不需要有对象租用的。只有需要保留状态的对象,无论是服务器激活的Singleton 还是客户端激活的对象才需要对象租用。

     租约

     生命周期

     发起人(Sponsor) 

    下面是NET Remoting 为管理远程对象的生存期管理的架构:

    ILease 接口定义了很多用于管理对象生存期的属性:

    • InitialLeaseTime。确定租用最初的有效期。
    • RenewOnCallTime。在每个方法调用后,更新此时间单元的租用。
    • SponsorshipTimeout。负责人通知租用过期后,Remoting 要等待的时间。
    • CurrentLeaseTime。距租用到期的时间(只读)。
    续约的方法有3种:
    1)隐式续约:当客户调用远程对象上的方法时,租约的隐式续借会自动进行。
    2)显示续约:通过ILease接口的Renew()方法完成。通过调用透明代理对象的GetLifeService()方法,就可以使用ILease接口。
    3)发起租约:客户可以创建一个实现ISponsor接口的发起者,并使用ILease接口的Register()方法在租约服务中注册这个发起者。发起者定义租约延长的时间。当租约到期时,发起者就要求延长租约时间。如果长期租约服务器上的远程对象,可以使用这个发起租约机制。

    开发Remoting三步走

    1、 远程对象: 

        建立类库项目:General 

    public class ClientActivatedType : MarshalByRefObject
    {
        
    public override Object InitializeLifetimeService()
        {
            
    //ILease接口定义了有关生命周期的属性,均为TimeSpan值
            ILease lease = (ILease)base.InitializeLifetimeService();
            
    //该租约状态。
            if (lease.CurrentState == LeaseState.Initial)
            {
                
    //初始化有效时间,默认值为300秒,如果为0,表示永不过期;
                lease.InitialLeaseTime = TimeSpan.FromSeconds(3); //这个3改成0,永远不过期。
                
    //超时值,通知Sponsor(发起人)租用过期后,Remoting会等待的时间,默认值为120秒;
                lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
                
    //调用远程对象一个方法时的租用更新时间,默认值为120秒;
                lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
            }
            
    return lease;
        }
        
    public string RemoteMethod()
        {
            Console.WriteLine(
    "ClientActivatedType.RemoteMethod called.");
            
    return "RemoteMethod called. " + WindowsIdentity.GetCurrent().Name;
        }

    } 

    2、服务端建立控制台项目:Server

    public class Server
    {
        
    public static void Main(string[] Args)
        {
            
    //读取配置文件
            RemotingConfiguration.Configure("server.exe.config");

            Console.WriteLine(
    "The server is listening. Press Enter to exit....");
            Console.ReadLine();

            Console.WriteLine(
    "Recycling memory...");
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

    服务器端配置文件  App.config 

    <configuration>
        
    <system.runtime.remoting>
            
    <application>
                
    <service>
                    
    <activated type="ClientActivatedType, General"/>
                
    </service>
                
    <channels>
                    
    <channel port="8080" ref="http">
                        
    <serverProviders>
                            
    <formatter ref="soap" typeFilterLevel="Full"/>
                            
    <formatter ref="binary" typeFilterLevel="Full"/>
                        
    </serverProviders>
                    
    </channel>
                
    </channels>
            
    </application>
        
    </system.runtime.remoting>
    </configuration>

    (1) 首先建立如上的监控处理类;

    (2) 注册通道:

    TcpChannel channel = new TcpChannel(8080);

    ChannelServices.RegisterChannel(channel);

    (3) 设置租用管理器的初始租用时间为无限:

    LifetimeServices.LeaseTime = TimeSpan.Zero;

    (4) 创建该跟踪处理类的实例,并注册跟踪服务:

    TrackingServices.RegisterTrackingHandler(new MyTracking());

    (5) 编组两个远程对象:

    ServerAS.AppService1 service1 = new ServerAS1.AppService1();

    ObjRef objRef1 = RemotingServices.Marshal((MarshalByRefObject)service1,"AppService1");

    ServerAS.AppService2 service2 = new ServerAS1.AppService2();

    ObjRef objRef2 = RemotingServices.Marshal((MarshalByRefObject)service2,"AppService2");

    (6) 使服务器端保持运行:

    Console.WriteLine("Remoting服务启动,按退出..."); 

    Console.ReadLine();

    3、客户端:建立控制台项目:Client

    public class Client
    {
        
    public static void Main(string[] Args)
        {
            RemotingConfiguration.Configure(
    "client.exe.config");

            ClientActivatedType CAObject 
    = new ClientActivatedType();
            
    //租用
            ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
            
    //发起人(Sponsor) 续租时间
            MyClientSponsor sponsor = new MyClientSponsor();
            
    // Register()或Renewal()方法来注册远程对象或延长生命周期
            serverLease.Register(sponsor);

            Console.WriteLine(
    "Client-activated object: " + CAObject.RemoteMethod());
            Console.WriteLine(
    "Press Enter to end the client application domain.");
            Console.ReadLine();
        }
    }
    //发起人(Sponsor)
    public class MyClientSponsor : MarshalByRefObject, ISponsor
    {
        
    private DateTime lastRenewal;
        
    public MyClientSponsor()
        {
            lastRenewal 
    = DateTime.Now;
        }
        
    public TimeSpan Renewal(ILease lease)
        {
            Console.WriteLine(
    "I've been asked to renew the lease.");
            Console.WriteLine(
    "Time since last renewal:" + (DateTime.Now - lastRenewal).ToString());
            lastRenewal 
    = DateTime.Now;
            
    return TimeSpan.FromSeconds(20);
        }
    }

     客户端配置文件  App.config 

    <configuration>
        
    <system.runtime.remoting>
            
    <application>
                
    <client url="http://localhost:8080">
                    
    <activated type="ClientActivatedType, General"/>
                
    </client>
                
    <channels>
                    
    <channel ref="http" port="0">
                        
    <serverProviders>
                            
    <formatter ref="soap" typeFilterLevel="Full"/>
                            
    <formatter ref="binary" typeFilterLevel="Full"/>
                        
    </serverProviders>
                    
    </channel>
                
    </channels>
            
    </application>
        
    </system.runtime.remoting>

    </ configuration>


        通过Marshal编组的对象要受到租用的生命周期所控制。注意对象被Disconnect,并不是指这个对象被GC回收,而是指这个对象保存在通道的相关代理信息被断开了,而对象本身仍然在服务器端存在。

        所以我们通过Remoting提供服务,应根据实际情况指定远程对象的生命周期,如果不指定,则为Remoting默认的设定。要让所有的远程对象永久有效,可以通过配置文件或租用管理器将初始有效时间设为0。

  • 相关阅读:
    [改善Java代码]在equals中使用getClass进行类型判断
    [改善Java代码]equals应该考虑null值的情景
    [改善Java代码]覆写equals方法时不要识别不出自己
    [改善Java代码] 推荐使用序列化实现对象的拷贝
    [改善Java代码]避免对象的浅拷贝
    [改善Java代码]让工具类不可实例化
    [改善Java代码]建议40:匿名类的构造函数很特殊
    [改善Java代码]使用匿名类的构造函数
    [改善Java代码]使用静态内部类提高封装性
    [改善Java代码]构造函数尽量简化
  • 原文地址:https://www.cnblogs.com/luomingui/p/2101779.html
Copyright © 2020-2023  润新知