Friday, September 7, 2007

REMOTING


Introduction

Microsoft® .NET remoting provides a framework that allows objects to interact with one another across application domains. The framework provides a number of services, including activation and lifetime support, as well as communication channels responsible for transporting messages to and from remote applications. Formatters are used for encoding and decoding the messages before they are transported by the channel. Applications can use binary encoding where performance is critical, or XML encoding where interoperability with other remoting frameworks is essential. All XML encoding uses the SOAP protocol in transporting messages from one application domain to the other. Remoting was designed with security in mind, and a number of hooks are provided that allow channel sinks to gain access to the messages and serialized stream before the stream is transported over the channel.

Managing the lifetime of remote objects without support from the underlying framework is often cumbersome. .NET remoting provides a number of activation models to choose from. These models fall into two categories:

· Client-activated objects

· Server-activated objects

Client-activated objects are under the control of a lease-based lifetime manager that ensures that the object is garbage collected when its lease expires. In the case of server-activated objects, developers have a choice of selecting either a "single call" or "singleton" model. The lifetime of singletons are also controlled by lease-based lifetime.

Remote Objects

One of the main objectives of any remoting framework is to provide the necessary infrastructure that hides the complexities of calling methods on remote objects and returning results. Any object outside the application domain of the caller should be considered remote, even if the objects are executing on the same machine. Inside the application domain, all objects are passed by reference while primitive data types are passed by value. Since local object references are only valid inside the application domain where they are created, they cannot be passed to or returned from remote method calls in that form. All local objects that have to cross the application domain boundary have to be passed by value and should be marked with the [serializable] custom attribute, or they have to implement the ISerializable interface. When the object is passed as a parameter, the framework serializes the object and transports it to the destination application domain, where the object will be reconstructed. Local objects that cannot be serialized cannot be passed to a different application domain and are therefore nonremotable.

Any object can be changed into a remote object by deriving it from MarshalByRefObject. When a client activates a remote object, it receives a proxy to the remote object. All operations on this proxy are appropriately indirected to enable the remoting infrastructure to intercept and forward the calls appropriately. This indirection does have some impact on performance, but the JIT compiler and execution engine (EE) have been optimized to prevent unnecessary performance penalties when the proxy and remote object reside in the same application domain. In cases where the proxy and remote objects are in different application domains, all method call parameters on the stack are converted into messages and transported to the remote application domain, where the messages are turned back into a stack frame and the method call is invoked. The same procedure is used for returning results from the method call.

Proxy Objects

Proxy objects are created when a client activates a remote object. The proxy object acts as a representative of the remote object and ensures that all calls made on the proxy are forwarded to the correct remote object instance. In order to understand exactly how proxy objects work, we need to examine them in more detail. When a client activates a remote object, the framework creates a local instance of the class TransparentProxy that contains a list of all classes, as well as interface methods of the remote object. Since the TransparentProxy class is registered with the CLR when it gets created, all method calls on the proxy are intercepted by the runtime. Here the call is examined to determine if it is a valid method of the remote object and if an instance of the remote object resides in the same application domain as the proxy. If this is true, a simple method call is routed to the actual object. If the object is in a different application domain, the call parameters on the stack are packaged into an IMessage object and forwarded to a RealProxy class by calling its Invoke method. This class (or rather an internal implementation of it) is responsible for forwarding messages to the remote object. Both the TransparentProxy and RealProxy classes are created under the covers when a remote object is activated, but only the TransparentProxy is returned to the client.

In order to gain a better understanding of these proxy objects, we need to take a detour and briefly mention ObjRef. A detailed description of ObjRef is provided in the Activation section. The following scenario describes briefly how ObjRef and the two proxy classes are related. It is important to note that this is a very broad description of the process; some variations exist, depending on whether objects are client or server activated, and if they are singleton or single-call objects.

· A remote object is registered in an application domain on a remote machine. The object is marshaled to produce an ObjRef. The ObjRef contains all the information required to locate and access the remote object from anywhere on the network. This information includes the strong name of the class, the class's hierarchy (its parents), the names of all the interfaces the class implements, the object URI, and details of all available channels that have been registered. The remoting framework uses the object URI to retrieve the ObjRef instance created for the remote object when it receives a request for that object.

· A client activates a remote object by calling new or one of the Activator functions like CreateInstance. In the case of server-activated objects, the TransparentProxy for the remote object is produced in the client application domain and returned to the client, no remote calls are made at all. The remote object is only activated when the client calls a method on the remote object. This scenario will obviously not work for client-activated objects, since the client expects the framework to activate the object when asked to do so. When a client calls one of the activation methods, an activation proxy is created on the client and a remote call is initiated to a remote activator on the server using the URL and object URI as the endpoint. The remote activator activates the object, and an ObjRef is streamed to the client, where it is unmarshaled to produce a TransparentProxy that is returned to the client.

· During unmarshaling, the ObjRef is parsed to extract the method information of the remote object and both the TransparentProxy and RealProxy objects are created. The content of the parsed ObjRef is added to the internal tables of the TransparentProxy before the latter is registered with the CLR.

The TransparentProxy is an internal class that cannot be replaced or extended. On the other hand, the RealProxy and ObjRef classes are public and can be extended and customized when necessary. The RealProxy class is an ideal candidate for performing load balancing for example, since it handles all function calls on a remote object. When Invoke is called, a class derived from RealProxy can obtain load information about servers on the network and route the call to an appropriate server. Simply request a MessageSink for the required ObjectURI from the Channel and call SyncProcessMessage or AsyncProcessMessage to forward the call to the required remote object. When the call returns, the RealProxy automatically handles the return parameter.

Here's a code snippet that shows how to use a derived RealProxy class.

MyRealProxy proxy = new MyRealProxy(typeof(Foo));

Foo obj = (Foo)proxy.GetTransparentProxy();

int result = obj.CallSomeMethod();

The TransparentProxy obtained above can be forwarded to another application domain. When the second client attempts to call a method on the proxy, the remoting framework will attempt to create an instance of MyRealProxy, and if the assembly is available, all calls will be routed through this instance. If the assembly is not available, calls will be routed through the default remoting RealProxy.

An ObjRef can easily be customized by providing replacements for default ObjRef properties TypeInfo, EnvoyInfo, and ChannelInfo. The following code shows how this can be done.

public class ObjRef {

public virtual IRemotingTypeInfo TypeInfo

{

get { return typeInfo;}

set { typeInfo = value;}

}

public virtual IEnvoyInfo EnvoyInfo

{

get { return envoyInfo;}

set { envoyInfo = value;}

}

public virtual IChannelInfo ChannelInfo

{

get { return channelInfo;}

set { channelInfo = value;}

}

}

Channels

Channels are used to transport messages to and from remote objects. When a client calls a method on a remote object, the parameters, as well as other details related to the call, are transported through the channel to the remote object. Any results from the call are returned back to the client in the same way. A client can select any of the channels registered on the "server" to communicate with the remote object, thereby allowing developers the freedom to select the channels that best suit their needs. It is also possible to customize any existing channel or build new ones that use different communication protocols. Channel selection is subject to the following rules:

· At least one channel must be registered with the remoting framework before a remote object can be called. Channels must be registered before objects are registered.

· Channels are registered per application domain. There can be multiple application domains in a single process. When a process dies, all channels that it registers are automatically destroyed.

· It is illegal to register the same channel that listens on the same port more than once. Even though channels are registered per application domain, different application domains on the same machine cannot register the same channel listening on the same port. You can register the same channel listening on two different ports.

· Clients can communicate with a remote object using any registered channel. The remoting framework ensures that the remote object is connected to the right channel when a client attempts to connect to it. The client is responsible for calling RegisterChannel on the ChannelService class before attempting to communicate with a remote object.

All channels derive from IChannel and implement either IChannelReceiver or IchannelSender, depending on the purpose of the channel. Most channels implement both the receiver and sender interfaces to enable them to communicate in either direction. When a client calls a method on a proxy, the call is intercepted by the remoting framework and changed into a message that is forwarded to the RealProxy class (or rather, an instance of a class that implements RealProxy). The RealProxy forwards the message to the channel sink chain for processing.

This first sink in the chain is normally a formatter sink that serializes the message into a stream of bytes. The message is then passed from one channel sink to the next until it reaches the transport sink at the end of the chain. The transport sink is responsible for establishing a connection with the transport sink on the server side and sending the byte stream to the server. The transport sink on the server then forwards the byte stream through the sink chain on the server side until it reaches the formatter sink, at which point the message is deserialized from its point of dispatch to the remote object itself.

One confusing aspect of the remoting framework is the relationship between remote objects and channels. For example, how does a SingleCall remote object manage to listen for clients to connect to if the object is only activated when a call arrives?

Part of the magic relies on the fact that remote objects share channels. A remote object does not own a channel. Server applications that host remote objects have to register the channels they require as well as the objects they wish to expose with the remoting framework. When a channel is registered, it automatically starts listening for client requests at the specified port. When a remote object is registered, an ObjRef is created for the object and stored in a table. When a request comes in on a channel, the remoting framework examines the message to determine the target object and checks the table of object references to locate the reference in the table. If the object reference is found, the framework target object is retrieved from the table or activated when necessary, and then the framework forwards the call to the object. In the case of synchronous calls, the connection from the client is maintained for the duration of the message call. Since each client connection is handled in its own thread, a single channel can service multiple clients simultaneously.

Security is an important consideration when building business applications, and developers must be able to add security features like authorization or encryption to remote method calls in order to meet business requirements. To accommodate this need, channels can be customized to provide developers with control over the actual transport mechanism of messages both to and from the remote object.

HTTP Channel

The HTTP channel transports messages to and from remote objects using the SOAP protocol. All messages are passed through the SOAP formatter, where the message is changed into XML and serialized, and the required SOAP headers are added to the stream. It is also possible to configure the HTTP Channel to use the binary formatter. The resulting data stream is then transported to the target URI using the HTTP protocol.

TCP Channel

The TCP channel uses a binary formatter to serialize all messages to a binary stream and transport the stream to the target URI using the TCP protocol. It is also possible to configure the TCP channel to the SOAP formatter.

Activation

The remoting framework supports server and client activation of remote objects. Server activation is normally used when remote objects are not required to maintain any state between method calls. It is also used in cases where multiple clients call methods on the same object instance and the object maintains state between function calls. On the other hand, client-activated objects are instantiated from the client, and the client manages the lifetime of the remote object by using a lease-based system provided for that purpose.

All remote objects have to be registered with the remoting framework before clients can access them. Object registration is normally done by a hosting application that starts up, registers one or more channels with ChannelServices, registers one or more remote objects with RemotingConfiguration, and then waits until it is terminated. It is important to note that the registered channels and objects are only available while the process that registered them is alive. When the process quits, all channels and objects registered by this process are automatically removed from the remoting services where they were registered. The following four pieces of information are required when registering a remote object with the framework:

1. The assembly name in which the class is contained.

2. The Type name of the remote object.

3. The object URI that clients will use to locate the object.

4. The object mode required for server activation. This can be SingleCall or Singleton.

A remote object can be registered by calling RegisterWellKnownServiceType, passing the information above as parameters, or by storing the above information in a configuration file and then calling Configure, thus passing the name of the configuration file as a parameter. Either of these two functions can be used to register remote objects as they perform exactly the same function. The latter is more convenient to use since the contents of the configuration file can be altered without recompiling the host application.

.NET remoting enables you to build widely distributed applications easily, whether application components are all on one computer or spread out across the entire world. You can build client applications that use objects in other processes on the same computer or on any other computer that is reachable over its network. You can also use .NET remoting to communicate with other application domains in the same process. (For details about programming application domains.

.NET remoting provides an abstract approach to interprocess communication that separates the remotable object from a specific client or server application domain and from a specific mechanism of communication. As a result, it is flexible and easily customizable. You can replace one communication protocol with another, or one serialization format with another without recompiling the client or the server. In addition, the remoting system assumes no particular application model. You can communicate from a Web application, a console application, a Windows Service – from almost anything you want to use. Remoting servers can also be any type of application domain. Any application can host remoting objects and provide its services to any client on its computer or network.

To use .NET remoting to build an application in which two components communicate directly across an application domain boundary, you need to build only the following:

· A remotable object.

· A host application domain to listen for requests for that object.

· A client application domain that makes requests for that object.

Even in a complex, multiclient/multiserver application, .NET remoting can be thought of in this way. The host and the client application must also be configured with the remoting infrastructure and you must understand the lifetime and activation issues that the remoting infrastructure introduces.

0 comments;Click here for request info on this topic:

Post a Comment