Programming .NET Components : Marshaling-by-Reference Activation Modes (part 1) - Server-Activated Single Call

8/14/2012 5:40:29 PM
.NET supports two kinds of marshal-by-reference objects: client-activated and server- activated. The two kinds map to three activation modes: client-activated object, server-activated single-call, and server-activated singleton. The different activation modes control object state management, object sharing, the object lifecycle, and the way in which the client binds to an object. The client decides whether to use client-activated or server-activated objects. If the client chooses client-activated objects, just one activation mode is available. If the client chooses server-activated objects, it's up to the hosting app domain to decide whether the client will get a server-activated single-call object or a server-activated singleton object. These objects are called server-activated because it's up to the host to activate the object on behalf of the client and bind it to the client. The hosting app domain indicates to .NET which activation modes it supports, using server registration. The host can support both client- and server-activated objects, or just one of these types; it's completely at the discretion of the host. If it decides to support a server-activated mode, the host must register its objects either as single-call objects or as singleton objects, but not both.

1. Client-Activated Object

Client-activated object mode is the classic client/server activation mode: when a client creates a new object, the client gets a new object. That object is dedicated to the client, and it's independent of all other instances of the same class. Different clients in different app domains get different objects when they create new objects on the host . There are no limitations on constructing client-activated objects, and you can use either parameterized constructors or the default constructor. The constructor is called exactly once, when the client creates the new remote object; if parameterized constructors are used, .NET marshals the construction parameters to the new object. Clients can choose to share their objects with other clients, either in their own app domains or in other app domains. Like local objects, client-activated objects can maintain state in memory. To make sure the remote object isn't disconnected from the remoting infrastructure and collected by its local garbage collector, client-activated objects require leasing when they make cross-process calls, to keep the objects alive for as long as the clients are using them. Leasing, discussed later in this chapter, provides a timestamp extending the life of the object.

Client-activated object mode is similar to the default DCOM activation model, with one important difference: the host app domain must register itself as a host willing to accept client-activated calls before remote calls are issued. As mentioned earlier, this means the process containing the host app domain must be running before such calls are made.

Figure 1. With client-activated objects, each client gets an independent object to use

2. Server-Activated Single Call

The fundamental problem with the client-activated object mode is that it doesn't scale well. The server object may hold expensive or scarce resources, such as database connections, communication ports, or files. Imagine an application that has to serve many clients. Typically, these clients create the remote objects they need when the client application starts and dispose of them when the client application shuts down. What impedes scalability with client-activated objects is that the client applications can hold onto objects for long periods of time, while actually using the objects for only a fraction of that time. If your design calls for allocating an object for each client, you will tie up such crucial limited resources for long periods and will eventually run out of resources. A better activation model is to allocate an object for a client only while a call is in progress from the client to the object. That way, you have to create and maintain in memory only as many objects as there are concurrent calls, not as many objects as there are clients. This is exactly what the single-call activation mode is about: when the client uses a server-activated single-call object, for each method call .NET creates a new object, lets it service the call, and then discards it. Between calls, the client holds a reference to a proxy that doesn't have an actual object at the end of the wire. The following list shows how single-call activation works; its steps are illustrated in Figure 2.

  1. The object executes a method call on behalf of a remote client.

  2. When the method call returns, if the object implements IDisposable, .NET calls IDisposable.Dispose( ) on it. .NET then releases all references it has to the object, making it a candidate for garbage collection. Meanwhile, the client continues to hold a reference to a proxy and doesn't know that its object is gone.

  3. The client makes another call on the proxy.

  4. The proxy forwards the call to the remote domain.

  5. .NET creates an object and calls the method on it.

Figure 2. Single-call activation mode

2.1. Benefits of single-call objects

The obvious benefit of using single-call objects is the fact that you can dispose of the expensive resources the objects occupy long before the clients dispose of the objects. By the same token, acquiring the resources is postponed until they are actually needed by a client. Keep in mind that creating and destroying the object repeatedly on the object side without tearing down the connection to the client (with its client-side proxy) is a lot cheaper than creating and disposing of the object altogether. Another benefit is that even if the client isn't disciplined enough to explicitly discard the object, this has no effect on scalability, because the object is discarded automatically.

If the client does call IDisposable.Dispose( ) on the object, it has the detrimental effect of recreating the object just so the client can call Dispose( ) on it. This is followed by a second call to Dispose( ) by the remoting infrastructure.

2.2. Designing a single-call object

Although in theory you can use single-call activation on any component type, in practice, you need to design the component and its interfaces to support the single-call activation mode from the ground up. The main problem is that the client doesn't know it's getting a new object each time it makes a call. Single-call components must be state-aware; that is, they must proactively manage their state, giving the client the illusion of a continuous session. A state-aware object isn't the same as a stateless object. In fact, if the single-call object were truly stateless, there would be no need for single-call activation in the first place. A single-call object is created just before every method call and deactivated immediately after each call. Therefore, at the beginning of each call, the object should initialize its state from values saved in some storage, and at the end of the call, it should return its state to the storage. Such storage is typically either a database or the filesystem. However, not all of an object's state can be saved as-is. For example, if the state contains a database connection, the object must reacquire the connection at the beginning of every call and dispose of the connection at the end of the call, or in its implementation of IDisposable.Dispose( ).

Using single-call activation mode has one important implication for method design: every method call must include a parameter to identify the object whose state needs to be retrieved. The object uses that parameter to gets its state from the storage and not the state of another instance of the same type. Examples of such identifying parameters are the account number for bank account objects, the order number for objects processing orders, and so on. Example 1 shows a template for implementing a single-call class. The class provides the MyMethod( ) method, which accepts a parameter of type Param (a pseudo-type invented for this example) that identifies the object.

Example 1. Implementing a single-call component
public class Param
public class MySingleCallComponent : MarshalByRefObject,IDisposable
   public MySingleCallComponent( )
   public void MyMethod(Param objectIdentifier)
      DoWork( );
   void GetState(Param objectIdentifier)
   void DoWork( )
   void SaveState(Param objectIdentifier)
   public void Dispose( )
   /* Class members/state */


The object then uses the identifier to retrieve its state and to save the state back at the end of the method call.

Another design constraint when dealing with single-call objects has to do with constructors. Because .NET re-creates the object automatically for each method call, it doesn't know how to use parameterized constructors, or which parameters to provide to them. As a result, a single-call object can't have parameterized constructors. In addition, because the object is constructed only when a method call takes place, the actual construction call on the client side is never forwarded to the objects:

    MySingleCallComponent obj;
    obj = new MySingleCallComponent( ); //No constructor call is made
    obj.MyMethod( );//Constructor executes 
    obj.MyMethod( );//Constructor executes

Single-call activation clearly involves a trade-off between performance (the overhead of reconstructing the object's state on each method call) and scalability (holding on to the state and the resources it ties up). There are no hard-and-fast rules as to when and to what extent you should trade performance for scalability. You may need to profile your system and ultimately redesign some objects to use single-call activation and others not to use it.

2.3. Applying the single-call mode

The single-call activation mode (see Example 10-3) works well when the amount of work to be done in each method call is finite, and there are no more activities to complete in the background once a method returns. You should not spin off background threads or dispatch asynchronous calls back into the object, because the object will be disposed of once the method returns. Because the single-call object retrieves its state from some storage on every method call, single-call objects work very well in conjunction with a load-balancing machine, as long as the state repository is some global resource accessible to all machines. The load balancer can redirect calls to different machines at will, knowing that each single-call object can service the call after retrieving its state.

Enterprise Services JITA

.NET Enterprise Services offer a set of smart instance-management techniques for .NET serviced components. One of those services is just-in-time activation (JITA), which works much like single-call objects. JITA has a few advantages over single-call objects, mainly the ability to combine it with other Enterprise Services instance-management techniques (such as object pooling). 

  •  Programming .NET Components : Remoting - Remote Object Types
  •  Active Directory Domain Services 2008 : Seize the RID Master Role, Seize the PDC Emulator Role, Seize the Infrastructure Master Role
  •  Active Directory Domain Services 2008 : Seize the Schema Master Role, Seize the Domain Naming Master Role
  •  Synology DS212+
  •  QNAP TS-219P II Turbo NAS
  •  Netgear Readynas Duo V2
  •  Iomega Storcenter Ix2 Network Storage Cloud Edition
  •  Freecom Silverstore 2-Drive NAS 2TB
  •  IBM WebSphere Process Server 7 : Installing WID on Windows
  •  IBM WebSphere Process Server 7 : WebSphere Integration Developer overview
  •  D-LINK Sharecenter Shadow DNS-325
  •  Choosing A... NAS Device (Part 2)
  •  Choosing A... NAS Device (Part 1)
  •  Buffalo Linkstation Pro 2TB
  •  Collaborating via Blogs and Wikis : Evaluating Wikis for Collaboration
  •  Collaborating via Blogs and Wikis : Evaluating Blogs for Collaboration
  •  Collaborating via Social Networks and Groupware : Evaluating Online Groupware
  •  Collaborating via Social Networks and Groupware : Creating Groups on Social Networks
  •  Programming .NET Components : Remoting - Application Domains (part 2) - The AppDomain Class, The Host App Domain
  •  Programming .NET Components : Remoting - Application Domains (part 1)
    Top 10
    Microsoft .NET : Design Principles and Patterns - From Principles to Patterns (part 2)
    Microsoft .NET : Design Principles and Patterns - From Principles to Patterns (part 1)
    Brother MFC-J4510DW - An Innovative All-In-One A3 Printer
    Computer Planet I7 Extreme Gaming PC
    All We Need To Know About Green Computing (Part 4)
    All We Need To Know About Green Computing (Part 3)
    All We Need To Know About Green Computing (Part 2)
    All We Need To Know About Green Computing (Part 1)
    Master Black-White Copying
    On-Scene Portrait Photography Techniques
    Most View
    Windows Server 2003 : Fundamentals of Backup
    HP Envy 3D Ivy Bridge Version
    Architecting Applications for the Enterprise : UML Diagrams (part 3) - Sequence Diagrams
    CSL Switch Dual II MI357 : Bait And Switch
    Windows Phone 7 Development : Understanding Trial and Full Modes (part 1) - Using the IsTrial Method
    How To Buy… A Gaming Case (Part 1)
    Do You Need A Virtual Firewall?
    Sony Xperia Go - Designed With Extra Durability (Part 1) - Design and waterproof ability
    The Most Wanted Products That We Cannot Wait! – November 2012
    Helping Clients Buy What They Want And Love It
    Got Yourself A Fancy New Nexus Flexus
    Microsoft Surface and Its Competitors
    Microsoft ASP.NET 3.5 : Caching Application Data (part 3) - Practical Issues
    The Effect Of IOS And Facebook On Shutterbugs (Part 1)
    Intel Core i5-2500K
    Apple, Google to meet with Schumer over privacy concerns
    Visual Studio 2010 IDE : Exporting Templates
    Exploiting SQL Injection : Out-of-Band Communication
    Adobe Flash Catalyst CS5 : Using the Drawing Tools (part 2) - Draw ellipses and circles, Drawing lines, Drawing other shapes, Adding text
    Best Photo Printers Revealed – Jan 2013 (Part 6)