.NET Remoting - Part I...
Remoting provides a flexible architecture for distributed applications in .NET. This series of articles shall examine the topic of remoting.
Part I: Introductory Theory: Processes, Applications, Distributed Applications
Knowledge assumed for series: VB.NET, VS.NET
Remoting provides a flexible architecture for distributed applications in .NET. This series of articles shall examine the topic of remoting. In particular I shall be looking at the following sections of information:
1. Introductory theory: Processes, Applications, Distributed Applications
2. .NET Remoting Architecture
3. Applying .NET Remoting
Creating a remotable class
Creating a server activated object
Creating a client activated object
Configuration issues
Interface assemblies
IIS
Asynchronous remoting
In this first article I'll attempt to summarise and introduce the necessary background theory of sections 1 and 2 before proceeding in article II to demonstrate the practical application of the theory which shall continue into article III.
A process is an application under execution. Windows isolates processes from one another so that the code running in one process cannot adversely affect other processes. Such process isolation ensures that:
Such process and application isolation thus has obvious benefits but the necessary process handling is resource intensive, notably the activity of process switching (so that each process receives its allocated share of CPU time).
Things are slightly different when it comes to .NET. The Common Language Runtime (CLR) provides a managed execution environment for .NET applications. The characteristics of the CLR allow the provision of isolation between running applications at a lower resource cost than a process boundary.
Within the CLR, instead of the fundamental unit of isolation being a process it is an application domain (AppDomain) and several AppDomains can run within a single process. This is achieved while also providing the same level of isolation between applications as provided by a Windows process. Further with less processes, the overhead of process switching becomes less of an issue and the performance of applications is increased as a consequence.
You can programmatically create AppDomins but normally they are created and managed by the runtime hosts that execute your code. By default with the .NET Framework three runtime hosts are configured for use: Windows shell, ASP.NET and Internet Explorer.
You may be wondering 'why IE?' at this point. Internet Explorer creates application domains in which to run managed controls. The .NET Framework supports the download and execution of browser-based controls. The runtime interfaces with the extensibility mechanism of Microsoft Internet Explorer through a mime filter to create application domains in which to run the managed controls. By default, one application domain is created for each Web site.
So, both process and application domains provide boundaries between applications affording their necessary protection and as part of this protection objects situated on either side of these boundaries are not permitted to communicate with each other.
This is obviously going to be a problem in the world of distributed applications they need to support a mechanism for enabling such communication. We'll return to how remoting enables such communication shortly but first, why would we want to implement our application in a distributed fashion? Well, a distributed application has the potential to improve on a non-distributed solution in the following areas: availability, scalability and robustness. For enterprise application these are highly desirable features.
Several efforts have been made to design frameworks for developing distributed applications, for example:
Most of these are still widely deployed in enterprises. However they all have limitations that mean they fail on one or more of the following criteria:
.NET provides two main pre-built frameworks for designing and implementing distributed applications: .NET remoting and ASP.NET WebServices. Both offer similar functionality and in fact, WebServices are built on the .NET remoting infrastructure. So why would you choose one over the other? The choice depends on the type of application you want to create:
You should use .NET remoting when both the client and server of the distributed application are under your control, for example when an application is being designed for use within a corporate network.
You should used ASP.NET WebServices when you do not have such control, for example when your application is interoperating with an application of a business partner.
.NET remoting allows communication between programmatic objects in different application domains and, particularly, application domains that are separated across the network. In these instances remoting transparently handles the details concerned with the necessary network communication.
The key question to address is: how can remoting establish cross-application domain communication when an application domain does not allow direct calls across its boundary? This is achieved, as with WebServices, via proxies. A proxy is an abstraction of the actual object required that can be treated as if it were the real object.
When a client object wishes to create an instance of a server object the remoting system on the client side instead creates a proxy of the server object. Thus as far as the client is concerned the server object is in the client's process the proxy deals with any complexities arising from the fact that this is not in fact the case.
When the client makes a request of the proxy the remoting system, which is overseeing the proxy activity, passes this request on to the remoting system on the server via a communication channel established between the two application domains.
The remoting system on the server handles the request, passing it on to the server object for action. The results are passed back to the server remoting system from the server object, which then passes these on back to the client via the established communication channel. The remoting system at the client then passes the results onto the client object via the proxy.
The process of packaging and sending method calls between the objects and across application boundaries via serialisation and deserialization as described above is known as marshalling. Object marshalling is a key concept which we shall now discuss before continuing to other important topics.
To facilitate remoting we need remotable objects objects that can be marshalled across the application domains. There are two types of remotable objects, marshalled either by value or by reference:
As you might have guessed from your parameter passing knowledge, MBV objects are copied and passed from the server application domain to the client application domain. When the client invokes a method on the MBV object it is serialized and transferred over the network to the client. The called method can then be invoked directly on the client and the object is no longer a remote object no marshalling or proxy is required as the object is now locally available.
MBV can provide faster performance as network roundtrips are reduced but for large objects you have the initial overhead of transferring them from server to client. Further, you are consuming additional client resources as the object is no longer running on the server.
MBR objects are accessed on the client side using a proxy. The client just holds a reference to these objects. Thus these are true remote objects and are preferable when the objects are large and/ or complex and require the server environment to function properly.
Channels are the devices that facilitate the communication across remoting boundaries. The .NET remoting framework ensures that before a remote object can be called, it has registered at least one channel with the remoting system on the server. A client object must similarly specify a channel to use when communicating with the remote object.
A channel has two end points. The channel object at the receiving end of a channel (the server) listens for a particular protocol using a specified port number, whereas the channel object at the sending end of the channel (the client) sends information to the receiving end using the protocol and port number specified by the channel object on the receiving end.
To participate in .NET remoting the channel object at the receiving end must implement the IChannelReceiver interface while the channel object at the sending end must implement the IChannelSender interface.
Which protocols can you use for channel communication? The .NET Framework provides implementations for HTTP (Hypertext Transfer Protocol) and TCP (Transmission Control Protocol). The tools are also available to allow the programmer to define their own channel communication protocol implementation if so desired.
Why would you choose HTTP over TCP and vice versa? Here are a few pointers:
Formatters are the objects used to encode and serialize data into an appropriate format before they are transmitted over a channel. For .NET remoting the formatter must implement the IFormatter interface. Two such formatter classes are provided within .NET: BinaryFormatter and SoapFormatter. If your requirements differ from those satisfied by these two classes you can and should build your own.
You will no doubt have heard of SOAP (Simple Object Access Protocol), probably in connection with Web Services, and you will also no doubt know that it is an XML based protocol for exchanging information between applications. SOAP is an extensible and modular protocol not bound to a particular transport mechanism such as HTTP or TCP.
As you might expect from its Web Services background, SOAP is ideal for communicating between applications that use incompatible architectures. However, SOAP is very verbose as you might again expect from the use of text based XML. The equivalent binary messages transfer information much more efficiently. However, the binary format used by .NET is proprietary and hence can only be understood by other .NET applications. These considerations should guide your choice of formatter class.
Thus we have a trade-off between efficiency and interoperability as we look at the combinations of supplied channels and formatters in .NET. In decreasing order of efficiency but increasing interoperability these combinations are:
| TCP, binary | most efficient, least interoperable |
| TCP, SOAP | |
| HTTP, binary | |
| HTTP, SOAP | least efficient, most interoperable |
Note that by default, the HTTP channel uses the SOAP formatter and the TCP channel uses the binary formatter.
Recall the distinction between MBV and MBR objects: it is only MBR objects that can be activated remotely as MBV objects are transferred to the client. MBR objects can be server-activated or client-activated.
Server Activated Objects (SAOs) are remote objects whose lifetime is controlled by the server. The remote object is instantiated/ activated when the client calls a method on the proxy object.
SAOs can only be instantiated using their default (parameter-less) constructors.
SAOs can be activated in two modes:
Firstly, SingleCall: an object is instantiated to service a single client request, after which it is garbage collected. They are also known as stateless because they cannot store state between requests as there is only one request. SingleCall potentially allows for greater server scalability. This is the appropriate choice when:
Secondly, Singleton: one object services the requests of all clients. Also known as stateful as they can maintain state across requests. This state however is globally shared between all clients which generally limits the usefulness of storing state information. Its lifetime is determined by the 'lifetime lease' of the object, a concept we'll return to in the next section. This is an appropriate choice when:
In contrast to SAOs, Client Activated Objects (CAOs) are remote objects whose lifetime are directly controlled by the client. CAOs are created on the server as soon as the client requests that the object be created there is no delay until a method call is made. Further a CAO can be created using any of the available constructors of the class it is not limited as per SAOs. A CAO instance serves only the client that created it, and the CAO does not get discarded with each request thus a CAO can maintain state for each client it is serving but it cannot share common state. Again lifetime is determined by 'Lifetime Leases', to be detailed shortly. CAOs are appropriate when:
The different activation types offer a compromise between flexibility and scalability, in increasing order of flexibility and decreasing scalability:
| singlecall server | most scalable, least flexible |
| singleton server | |
| client activation | least scalable, most flexible |
A lifetime lease is the period of time an object will remain in memory until its resources are reclaimed by the Framework. Singleton SAOs and CAOs use lifetime leases.
A lifetime lease is represented by an object that implements the ILease interface. The object would normally work as follows:
In this article I've presented an overview of the background information necessary before we progress to examine the practicalities of the remoting architecture. This we shall do in articles II and III in this series of three articles.
.NET SDK
Developing XML WebServices and Server Components with VB.NET and the .NET Framework
Mike Gunderloy
Que