有关Remoting的几个结论与论证

整体:

Remoting的激活方式有两种客户端激活和服务端激活,顾名思义服务端激活就是服务端负责维护远程服务对象的创建与销毁而客户端激活则是客户端负责远程对象的创建与激活。在服务端激活的模式下根据请求来建立对象,对所有请求建立一个对象的就是 Singleton而对每次请求都分别建立对象的叫做SingleCall。SingleCall建立的对象系统自己回收没有生命周期之说而对于Singleton你可以通过编程或是配置来管理远程服务对象的生命周期。在客户端激活的模式下远程服务端会为每个客户端建立远程对象客户端持有这个远程对象的引用。总之客户端激活的时间是在客户端请求的时候,而服务端激活远程对象的时间是在调用对象方法的时候。 


1:SingleCall 与 Singleton

结论:SingleCall在每次用户调用服务端代理的时候服务端会为每次请求构造一个新的对象而Singleton则对所有请求建立一个对象。

论证:我们可以建立一个服务端对象并使其拥有一个整型变量,在其构造函数的时候赋值为1然后在方法中将值加1放回。对于SingleCall每次请求永远为2而Singleton则会随着请求次数增加而增加。

代码示意:

代码
    public class Test : MarshalByRefObject, ITest
    {
        private int Num = 0;
        public Test()
        {
            Num = 1;
        }

        #region ITest 成员

        public string GetUserName(string Name)
        {
            //return TestSingle.GetInstance().GetUserName(Name);
            return string.Format("UserName:{0}", Name);
        }

        public int Cout()
        {
            //return TestSingle.GetInstance().Cout();
            Num++;
            return Num;
        }

        #endregion
    }

引深:

从这里我们可以看出来, SingleCall天生具有负载均衡的能力,可以用在大规模请求的处理上。但是如何让SingleCall具有Singleton的能力那?这就需要理解SingleCall的含义。其实SingleCall只是每次请求的时候建立新的对象,就是你声明的对象但是服务端的容器还是一个。这个时候我们就可以在服务端建立一个单件对象用于存储或是计算。这样就可以兼顾SingleCall和Singleton的优势。如果不是很明白你可以看下面的代码

代码
    public class TestSingle
    {
        private static readonly object obj = new object();
        private static TestSingle Instance;

        private int Num = 0;

        private TestSingle()
        {
            Num = 1;
        }

        public static TestSingle GetInstance()
        {
            if (Instance == null)
                lock (obj)
                {
                    if (Instance == null)
                        Instance = new TestSingle();
                }

            return Instance;
        }

        public string GetUserName(string Name)
        {
            return string.Format("UserName:{0}", Name);
        }

        public int Cout()
        {
            Num++;
            return Num;
        }
    }

2:客户端激活

结论:客户端激活模式下服务端会为每个客户端建立一个远程服务对象

论证:还是采用上面的例子

代码示意:

代码
            TcpChannel channel = new TcpChannel(61000);
            ChannelServices.RegisterChannel(channel);
            RemotingConfiguration.ApplicationName = "RemoteServer";
            RemotingConfiguration.RegisterActivatedServiceType(typeof(ITest.Test));


            object[] attrs = { new UrlAttribute("tcp://localhost:61000/RemoteServer") };
            ObjectHandle handle = Activator.CreateInstance("ITest",
                                   "ITest.Test", attrs);
            ITest.Test obj = (ITest.Test)handle.Unwrap();


            Console.WriteLine(obj.Cout());

我们每次运行客户端代码永远得到2

3:租约

对于服务端激活的Singleton模式或是客户端激活模式下可以自己设置服务端对象的生命周期,这个周期就是租约设置项如下

LeaseTime选项可以定义远程对象的最长租借时间,默认300秒

RenewOnCallTime递增租借时间,默认120秒

SponsorshipTimeout调用结束之前的那段默认时间,默认120秒

LeaseManagerPollTime发起人必须返回延长的那部分租借时间,默认10秒

就是说远程服务对象会在服务端保存LeaseTime秒,在LeaseTime秒内如果发生请求则服务端生命周期会延长RenewOnCallTime秒。

结论:服务端激活模式下的Singleton激活的远程对象存活LeaseTime秒

论证:还是上面的例子 

示意代码:

代码
                LifetimeServices.LeaseTime = TimeSpan.FromSeconds(1);
                LifetimeServices.RenewOnCallTime = TimeSpan.FromSeconds(1);
                LifetimeServices.LeaseManagerPollTime = TimeSpan.FromSeconds(1);
                LifetimeServices.SponsorshipTimeout = TimeSpan.FromSeconds(1);
            
                TcpServerChannel channel = new TcpServerChannel(61000);
                ChannelServices.RegisterChannel(channel, false);
                RemotingConfiguration.RegisterWellKnownServiceType(typeof(ITest.Test), "SVRCALL.rem",
                  WellKnownObjectMode.Singleton);


            ITest.ITest test = (ITest.ITest)Activator.GetObject(typeof(ITest.ITest), @"tcp://10.53.139.138:61000/SVRCALL.rem");
            Console.WriteLine(test.Cout());

运行多次客户端虽然是Singleton但是Num不会递加每次都是2。 

原文地址:https://www.cnblogs.com/tommyli/p/1773812.html