Step by step remoting 2: activation mode
Activation modes of remote objectsServer activationAndClient ActivationThere are two types: (the object is divided into two types: server-side activation objects or well-known objects and client-side activation objects). First, let's look at how msdn describes server-side activation:
The active objects on the server are objects directly controlled by the server for their lifetime. The server application domain creates these objects only when the client calls the method on the object, instead of calling new or Activator on the client. create these objects when GetObject is created. This saves a network round-trip process for creating an instance. When a client requests an instance of the server activation type, only one proxy is created in the client application domain. However, this also means that when you use the default implementation, you can only use the default constructor for the type of server activation. To publish an instance, you can use the client to activate or dynamically publish your instance by using the type created by a specific constructor with parameters.
The server-activated objects have two activation modes (or the WellKnownObjectMode value): Singleton and SingleCall.
The Singleton type does not have multiple instances at any time. If an instance exists, all client requests are provided by the instance. If no instance exists, the server creates an instance, and all subsequent client requests are provided by this instance. Because the Singleton type has an associated default lifetime, even if there is no more than one available instance at all times, the client will not always receive a reference to the same instance of the class that can be remotely processed.
The SingleCall remote server type always sets an instance for each client request. The next method call will be performed by another instance. From the design perspective, the SingleCall type provides very simple functions. This kind of mechanism does not provide status management. If you need status management, this will be a disadvantage; if you do not need it, this kind of mechanism will be ideal. Maybe you only care about load balancing and scalability, but not the status. In this case, this mode will be your ideal choice, because there is only one instance for each request. If you want to, developers can provide their own state management to the SingleCall object, but such State data does not reside in the object, because each time a new method is called, a new object identifier will be instantiated.
First, we will conduct an experiment on the two modes activated by the server. We will make the following modifications to the remote object:
Using System;
Namespace RemoteObject
{
Public class myobject: marshalbyrefobject
{
Private int I = 0;
Public int add (int A, int B)
{
Return A + B;
}
Public int count ()
{
Return ++ I;
}
}
}
Make the following changes to the client: RemoteObject. myObject app = (RemoteObject. myObject) Activator. getObject (typeof (RemoteObject. myObject), System. configuration. configurationSettings. appSettings ["ServiceURL"]);
Console. WriteLine (app. Count ());
Console. ReadLine ();
1 is displayed when the client is opened for the first time, 2 is displayed when the client is opened for the second time, and so on ...... It is verified that the Singleton type does not have multiple instances at any time. If an instance exists, all client requests are provided by the instance. If no instance exists, the server creates an instance, and all subsequent client requests are provided by this instance.
Modify the server config:
<Wellknown type = "RemoteObject. MyObject, RemoteObject" objectUri = "RemoteObject. MyObject"
Mode = "SingleCall"/>
(Note the case-sensitive, uppercase C)
Re-run the server and client, and open multiple clients. The result is always 1. It is verified that the SingleCall type will recreate the instance for each client request. The next method call will be provided by another server instance.
Next let's talk about the activation mode of the client, which is written in msdn:
The objects activated by the client are the objects whose lifetime is controlled by the calling application domain, just as the object's lifetime is controlled by the calling application domain when the client is a local object. For client activation, a round-trip process occurs when the client tries to create an instance of the server object, and the client proxy is created using object reference (ObjRef, this object reference is obtained when a remote object is created on the server and returned. Each time a client creates a client-activated instance, the instance will only serve the specified reference in the specific client until its lease expires and its memory is recycled. If you call an application domain to create two remote instances, each client reference will only call a specific instance in the referenced server application domain.
For more information, see
1. The client activation time is when the client requests, while the server activates the remote object at the time when the object method is called.
Modify the remote object as follows: using System;
Namespace RemoteObject
{
Public class MyObject: MarshalByRefObject
{
Private int I = 0;
Public MyObject ()
{
Console. WriteLine ("Activate ");
}
Public int add (int A, int B)
{
Return A + B;
}
Public int count ()
{
Return ++ I;
}
}
}
Server Configuration File: <configuration>
<System. runtime. remoting>
<Application name = "RemoteServer">
<Service>
<Activated type = "RemoteObject. MyObject, RemoteObject"/>
</Service>
<Channels>
<Channel ref = "tcp" port = "9999"/>
</Channels>
</Application>
</System. runtime. remoting>
</Configuration>
Client Program: using system;
Namespace remoteclient
{
Class myclient
{
[Stathread]
Static void main (string [] ARGs)
{
// Remoteobject. myobject APP = (remoteobject. myobject) activator. GetObject (typeof (remoteobject. myobject), system. configuration. configurationsettings. deleettings ["serviceurl"]);
RemoteObject. myObject app = (RemoteObject. myObject) Activator. createInstance (typeof (RemoteObject. myObject), null, new object [] {new System. runtime. remoting. activation. urlAttribute (System. configuration. configurationSettings. appSettings ["ServiceURL"])});
// Console. WriteLine (app. Count ());
Console. ReadLine ();
}
}
}
Client configuration file: <configuration>
<Deleetask>
<Add key = "ServiceURL" value = "tcp: // localhost: 9999/RemoteServer"/>
</AppSettings>
</Configuration>
(The uri here is written according to the RemoteServer defined by the application element in the server configuration file)
When running the program, we can see that the server outputs "activation" when the client starts. We then turn back to the well-known mode for testing and find that only the running method outputs "activation" on the server ".
2. Client activation can call custom constructor. Unlike server activation, you can only use the default constructor.
Modify the client code as follows: RemoteObject. myObject app = (RemoteObject. myObject) Activator. createInstance (typeof (RemoteObject. myObject), new object [] {10}, new object [] {new System. runtime. remoting. activation. urlAttribute (System. configuration. configurationSettings. appSettings ["ServiceURL"])});
Console. WriteLine (app. Count ());
Here we can see that 10 is provided as the constructor parameter in the second parameter of the CreateInstance method. We cannot do this in server activation mode.
Modify the remote object construction method as follows:
Public MyObject (int k)
{
This. I = k;
Console. WriteLine ("Activate ");
}
Without a doubt, we run the client and find that the output is 11 instead of 1.
3. Through the above example, we run multiple clients and find that 11 always appears. Therefore, once the client activation mode obtains the client request, an instance reference is created for each client.
Summary:
1. remoting supports two remote objects: well-known and customer-activated. The well-known remote object uses URI as the identifier. The client program uses this URI to access those remote objects, which is also known as the reason. Two usage modes are available for well-known objects: singlecall and singleton. For the former, an object is created every time it is called, so the object is stateless. For the latter, the object is created only once, and all customers share the object state, so the object is stateful. Another client activation object is activated using the class type. The URI is dynamically created in the background and returned to the client program. The customer activation object is stateful.
2. For Singleton objects, scalability needs to be considered. Singleton objects cannot be deployed on multiple servers. If they need to be cross-server, Singleton cannot be used.
Note: For my personal habits, in my example, the server configuration uses the config file, and the client configuration is basically in the program mode.
Advantages of using the configuration file: You can configure the channel and remote object without re-compiling, and the amount of code written is relatively small.
Advantages of using program customization: You can obtain information during running and it is advantageous for program debugging.
Appendix: msdn chapters:
Http://msdn.microsoft.com/library/CHS/cpguide/html/cpconActivation.asp