[Transfer] Marshal, Disconnect and life cycle and tracking services of Microsoft .Net Remoting

Marshal, Disconnect and life cycle and tracking services

1. Activation of remote objects

There are three activation methods in Remoting. The general implementation is completed through the static method of the RemotingServices class. The working process is actually to register the remote object into the channel. Since Remoting does not provide a corresponding Unregister method to unregister a remote object, if you need to register/unregister a specified object, Microsoft recommends using Marshal (generally translated as marshalling) in conjunction with Disconnect. I have already mentioned in “Net Remoting Basics”: The Marshal() method converts the MarshalByRefObject class object into an ObjRef class object. This object stores all the relevant information required to generate a proxy to communicate with the remote object. This allows the instance to be serialized for transfer between application domains and over the network, and can be called by clients. The Disconnect() method disconnects the specific instance object from the channel.

According to the above description, the Marshal() method marshals the remote object by reference (Marshal-by-Reference, MBR) and puts the object’s proxy information into the channel. The client can obtain it through Activator.GetObject(). If the user wants to log out of the object, by calling the Disconnect() method. So is there life cycle management for grouped remote objects in this way? This is the problem this article describes.

2. Life cycle

In the CLR, the framework provides GC (garbage collector) to manage the life cycle of objects in memory. Similarly, .Net Remoting uses a distributed garbage collection based on leasing to manage the life cycle of remote objects.

Early DCOM management of object life cycles used ping and reference counting to determine when an object should be garbage collected. However, the network traffic caused by ping is a painful burden on the performance of distributed applications, which greatly affects the overall performance of distributed processing. .Net Remoting introduces a lease manager in each application domain, which holds a reference to the lease object for each server-side SingleTon, or for each client-activated remote object. (Note: For the SingleCall method activated on the server side, since it is stateless, each activated remote object is automatically recycled by the GC of the CLR. Therefore, there is no life cycle management for remote objects activated in the SingleCall mode. .)

1. Rent

A lease is an object that encapsulates a TimeSpan value and is used to manage the lifetime of remote objects. The ILease interface that defines the rental function is provided in .Net Remoting. When Remoting activates a remote object through SingleTon mode or client activation mode, the lease object calls the InitializeLifetimeService method inherited from System.MarshalByRefObject to request a lease from the object.

The ILease interface defines properties related to the life cycle, all of which are TimeSpan values. as follows:
InitialLeaseTime: initialization valid time, the default value is 300 seconds, if it is 0, it means it will never expire;
RenewOnCallTime: The lease renewal time when calling a method of the remote object, the default value is 120 seconds;
SponsorshipTimeout: timeout value, the time Remoting will wait after notifying the Sponsor (sponsor) that the lease has expired. The default value is 120 seconds;
CurrentLeaseTime: The current lease time, when the lease is obtained for the first time, is the value of InitializeLeaseTime.

Because the remote object of Remoting inherits MarshalByRefObject, it inherits the InitializeLifetimeService method by default, and the related properties of the lease are the default values. If you want to change these settings, you can override this method in the remote object. For example:

 public override object InitializeLifetimeService()
 {
  ILease lease = (ILease)base.InitializeLifetimeService();
  if (lease.CurrentState == LeaseState.Initial)
  {
   lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
   lease.RenewOnCallTime = TimeSpan.FromSeconds(20);
  }
  return lease;
 }

You can also ignore this method and change the object’s lease period to infinite:

public override object InitializeLifetimeService()
 {
  return null;
 }

2. Rental Manager

If the lease mentioned earlier is mainly applied to each specific remote object, then the lease manager is a server-side manager specifically used to manage the life cycle of remote objects. It maintains a System.Hashtable member to map the lease A System.DateTime instance representing when each lease should expire. Remoting uses polling to wake up the lease manager at a certain time and check whether each lease has expired. The default is to wake up every 10 seconds. The polling interval can be configured, such as setting the polling interval to 5 minutes: LifetimeService.LeaseManagerPollTime = System.TimeSpan.FromMinutes(5);

We can also set the properties of the remote object lease in the lease manager, such as changing the initial validity time of the remote object to permanent validity:
LifetimeServices.LeaseTime = TimeSpan.Zero;

We can also set the life cycle through configuration files, such as:
& amp;lt;configuration & amp;gt;
& amp;lt;system.runtime.remoting & amp;gt;
& amp;lt;application name = “SimpleServer” & amp;gt;
& amp;lt;lifetime leaseTime = “0” sponsorshipTimeOut = “1M” renewOnCallTime = “1M” pollTime = “30S”/ & amp;gt;
& amp;lt;/application & amp;gt;
& amp;lt;/system.runtime.remoting & amp;gt;
& amp;lt;/configuration & amp;gt;

Note: The pollTime in the configuration file is the LeaseManagerPollTime mentioned above as the polling interval of the lease manager.

The lease manager’s life cycle settings are for all remote objects on the server. When we set the lease properties through the configuration file or lease manager, the life cycle of all remote objects follows this setting, unless we change the relevant configuration for the specified remote object by overriding the InitializeLifetimeService method. That is, the remote object’s lease configuration takes precedence over the server-side configuration.

3. Sponsor

The initiator is for the client. The remote object is the object that the initiator wants to rent. The initiator can sign a lease with the server and agree on the lease time. Once it expires, the sponsor can also renew the lease, just like the tenant’s contract and the relationship between the landlord and the renter in real life.

The ClientSponsor class is defined in the System.Runtime.Remoting.Lifetime namespace in the .Net Framework, which inherits System.MarshalByRefObject and implements the ISponsor interface. For the properties and methods of the ClientSponsor class, please refer to MSDN.

To use the sponsor mechanism, the client must create an instance of the ClientSponsor class. Then call related methods such as Register() or Renewal() method to register the remote object or extend the life cycle. like:
RemotingObject obj = new RemotingObject();
ClientSponsor sponsor = new ClientSponsor();
sponsor.RenewalTime = TimeSpan.FromMinutes(2);
sponsor.Register(obj);

The lease renewal time can also be set directly in the constructor of ClientSponsor, such as:
ClientSponsor sponsor = new ClientSponsor(TimeSpan.FromMinutes(2));
sponsor.Register(obj);

We can also write our own Sponsor to manage the sponsor mechanism. This class must inherit ClientSponsor and implement the ISponsor interface.

3. Tracking Service

As mentioned before, we need to determine whether there is life cycle management for remote objects marshalled through Marshal. In Remoting, you can monitor the marshalling process of MBR objects through the tracking service program.

We can create a simple tracking handler that implements the interface ITrackingHandler. The interface ITrackingHandler defines three methods, MarshalObject, UnmarshalObject and DisconnectedObject. When the remote object is marshalled, unmarshaled, and disconnected, the corresponding methods are called. Here is the code for the tracking class:

public class MyTracking:ITrackingHandler
{
 publicMyTracking()
 {
  //
  // TODO: Add constructor logic here
  //
 }

 public void MarshaledObject(object obj,ObjRef or)
 {
  Console.WriteLine();
  Console.WriteLine("object" + obj.Tostring() + " is marshaled at " + DateTime.Now.ToShortTimeString());
 }

 public void UnmarshaledObject(object obj,ObjRef or)
 {
  Console.WriteLine();
  Console.WriteLine("object" + obj.Tostring() + " is unmarshaled at " + DateTime.Now.ToShortTimeString());
 }

  public void DisconnectedObject(object obj)
 {
  Console.WriteLine(obj.ToString() + " is disconnected at " + DateTime.Now.ToShortTimeString());
 }
}

Then create an instance of the tracking processing class on the server side and register the tracking service:

TrackingServices.RegisterTrackingHandler(new MyTracking());

4. Test

1. Create two remote objects and override the InitializeLifetimeService method:

Object 1: AppService1
Initial life cycle: 1 minute

public class AppService1:MarshalByRefObject
 {
  public void PrintString(string contents)
  {
   Console.WriteLine(contents);
  }

  public override object InitializeLifetimeService()
  {
   ILease lease = (ILease)base.InitializeLifetimeService();
   if (lease.CurrentState == LeaseState.Initial)
   {
    lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
    lease.RenewOnCallTime = TimeSpan.FromSeconds(20);
   }
   return lease;
   
  }
 }

Object two: AppService2

Initial life cycle: 3 minutes

public class AppService2:MarshalByRefObject
 {
  public void PrintString(string contents)
  {
   Console.WriteLine(contents);
  }

  public override object InitializeLifetimeService()
  {
   ILease lease = (ILease)base.InitializeLifetimeService();
   if (lease.CurrentState == LeaseState.Initial)
   {
    lease.InitialLeaseTime = TimeSpan.FromMinutes(3);
    lease.RenewOnCallTime = TimeSpan.FromSeconds(40);
   }
   return lease;
   
  }
 }

For simplicity, the methods are the same for both objects.

2. Server side

(1) First establish the monitoring and processing class as above;

(2) Registration channel:
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);

(3) Set the initial lease time of the lease manager to unlimited:
LifetimeServices.LeaseTime = TimeSpan.Zero;

(4) Create an instance of the tracking processing class and register the tracking service:
TrackingServices.RegisterTrackingHandler(new MyTracking());

(5) Group two remote objects:
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) Keep the server running:
Console.WriteLine(“Remoting service starts, press to exit…”);
Console.ReadLine();

3. Client

Obtain two remote objects through Activator.GetObject() and call its method PrintString. The code is omitted.

4. Run the test:

Run the server and client. Since the monitoring program will monitor the marshalling process of the remote object, at the beginning of the run, it will be displayed that the remote object has been Marshaled:

Then the client calls the PrintString method of these two remote objects, and the server accepts the string:

After one minute, the remote object is automatically Disconnected:

At this time, if the client wants to call remote object 1, a RemotingException will be thrown;

After another minute, remote object two was Disconnected:

align=”center”>

Users can also test whether the time of RenewOnCallTime is correct based on this code. That is to say, if the object is called when the object has not been Disconnected, from the moment the object is called, its life cycle is no longer the originally set initial effective time value (InitialLeaseTime), but the lease update time value ( RenewOnCallTime). In addition, if these two remote objects do not override the InitializeLifetimeService method, the life cycle should be the value set by the lease manager, which is permanently valid (set to 0). Then these two objects will not be automatically Disconnected unless we explicitly specify to close its connection. Of course, if we close the connection explicitly, the tracer will still monitor its changes and then display them.

5. Conclusion

Through our testing, the conclusion is actually obvious. Objects marshalled through Marshal are subject to lease life cycle control. Note that when an object is Disconnected, it does not mean that the object is recycled by GC, but that the relevant proxy information stored in the channel of the object is disconnected, while the object itself still exists on the server side.

Therefore, when we provide services through Remoting, we should specify the life cycle of the remote object according to the actual situation. If not specified, it will be the default setting of Remoting. To make all remote objects permanently valid, you can set the initial validity time to 0 through the configuration file or the lease manager.

Original address: http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html