An Overview of .NET Remoting

As we have seen, the .NET makes generous use of XML metadata. From XML comments to remote Web Service discovery and execution, the .NET uses metadata to make software components more self-descriptive. This promotes loose, run-time coupling of objects and applications in a development environment rich with opportunity.

Inter-application object sharing need not be limited to Web Services. The .NET Remoting infrastructure encompasses many different levels of interobject and interapplication communication. In this section we will cover the .NET platform's support for distributed objects. We will touch on how Web Services relate to remotable objects. We will then explore some fine-grained remote programming techniques that the .NET platform also provides. This discussion will include conceptual overviews as well as detailed code samples.

Remote Web Services

Remote Web Services are ideal for publishing course-grained application methods to the widest possible consumer audience. Because Web Services rely exclusively on open, ubiquitous standards such as HTTP, SOAP, and XML for communication, they are accessible to any type of Internet application.

Web Services are also useful for publishing software to an unknown user base. A good example of a Web Services candidate is our Noverant.com online CD store. As its volume increases, Noverant might want to consider exposing its CD purchasing business logic through a Web Service. This would allow partners and customers to create orders directly through software, bypassing a tedious Web site. Custom Noverant Web Service clients, built in a .NET studio, Notepad, or any other development toolset, could be written to browse and purchase items from the Noverant CD catalog.

Web Services are fantastic, but when do you not want to use them? Unfortunately, Web Services do have a few limitations. All Web Service objects are passed by value through SOAP. Pass-by-reference is not supported. A certain amount of overhead is associated with calls to Web Services. Objects need to be marshaled into (potentially large) XML SOAP documents and return results need to be unmarshaled. Furthermore, reliance on HTTP makes Web Services stateless in nature. Web Service connections are closed upon the completion of any call to a Web method.

These limitations make Web Services less suitable for fine-grained object sharing. Fortunately, the .NET Common Language Runtime (runtime) engine has support for a wide variety of distributed object sharing and messaging. The following feature list is an excerpt from the .NET Framework Developer's Guide.

  • The ability to publish and consume services and objects across a wide variety of application types. Applications that can participate in remote services include console applications, Microsoft Windows GUI applications, IIS-based Web applications, ASP .NET Web Services, or local Windows services.
  • The preservation of full managed-code type-system fidelity.
  • The ability to pass objects by reference and to return to a particular object in a particular application domain.
  • Binary Object Serialization in addition to SOAP XML-based serialization.
  • The ability to control activation characteristics and object lifetimes directly.
  • The ability to implement and use third-party channels or protocols to extend communication to meet your specific needs.
  • Direct participation in the communication process to create the functionality you need.

.NET Remoting Overview

The .NET Remoting framework provides tools that allow applications to share objects and data over a network. Web Services are just one aspect of .NET Remoting. Trusted client applications might need to interact with server-side software components at the object level rather than the service level. The .NET Remoting framework provides these services and many others. Let's look at how the .NET Remoting framework relates to applications, messages, objects, and channels.

Applications, Messages, and Objects

Applications form loosely coupled communities in the .NET Remoting framework. They can communicate with each other at one of two levels.

  1. They can send high-level messages. These messages can contain different kinds of application data, including binary formats, XML text, plain text, or HTML.
  2. They can share actual objects with each other. The two applications do not need to be homogeneous in platform to communicate at the object level. Participating programs can be written in .NET C#, VB, Java, C, or COBOL. SOAP is used to promote loose coupling between applications at the object level. SOAP messages can be sent anywhere over HTTP and make ideal carriers for pass-by-value objects.

Applications that participate in remote transactions are isolated from one another in the .NET by Application Domains. One or more applications might reside inside a single application domain. The AppDomain class manages these entities. Its methods enable the runtime to load assemblies or threads into the domain, define dynamic assemblies, specify loading and termination events, and terminate the domain.

Channels

SOAP and other interapplication messages are transported through channels. Channels relay information between application domains, processes, and machines. Channels can either listen for new incoming messages or relay outbound messages to a destination channel. Channels are also responsible for converting messages into different wire formats. For example, the TcpChannel class converts outbound messages into a compact binary format and converts incoming messages from binary into their original format.

Channels implement the IChannel interface that defines the properties ChannelName and ChannelPriority. A session is created between each end of the channel. Sessions connect client and server "sinks." Sinks are responsible for relaying network messages along "sink chains" on both the client and the server. The client end of the channel resides at the end of the Client sink chain while the server end of the channel is at the front of the Server sink chain.

An Introduction to Remote Objects

The .NET Framework includes a rich library of tools for remote object sharing. The remoting framework allows objects to be marshaled by value or by reference to and from other applications on the network. In this section we will explore object marshaling, object activation, leases, and remote object configuration.

Marshal by Value

A client application can take a "brute force" approach to remoting by downloading an entire object—methods, properties and all—into its address space. The client can then interact with the object locally. The object's methods execute in the client's address space and can access resources intrinsic to the client's context, such as file systems and network connections. The process of copying an object or value from one address space into another is called "marshaling by value."

To accomplish this, the .NET Framework serializes the server object's entire class definition into a format that can be transmitted over the network, or channel. The serialized object can be represented in a binary format unique to the operating environment for optimal performance. Alternatively, the object can be serialized into an XML descriptor that can be reconstructed on any platform. Web Services employ the latter technique.

Almost any object can be marshaled by value. Any object that implements the ISerializable interface or implements its own serialization techniques can be transmitted by value (or copied) to another application.

Having a client download an entire object from a server is usually undesirable. It is an expensive operation that can require a lot of network bandwidth and client resources. Some classes have large method footprints that take time to serialize. In addition, transmitting an entire object over a network exposes that object's private instance variables to outsiders. Sometimes you do not have the option of downloading an entire object. In situations where the object needs to access resources unique to the server, such as a database or file system, you have no choice but to execute the object remotely. What should you do if you don't need the entire object but just need to call its methods remotely? Marshaling by reference might be the answer.

Marshal by Reference

The .NET Remoting framework supports marshal-by-reference objects as well as marshal-by-value ones. This means that a client application can download a reference to a remote object and interact with it as if it were locally defined. Although the object appears to "belong" to the client, its methods actually execute, via RPC, in the server's address space.

The .NET Remoting framework takes care of all the plumbing that makes remote object references work. Remote object references are actually stub classes generated by .NET. The stub class has the same method and property signature as the original class. The stub class, however, does not house any of the method implementations. Each call to a stub method begins a chain of events in which the method arguments are serialized and sent over the network to the remote object instance, where the actual method call is executed. The method's results are serialized, sent back to the client, unpackaged, and returned to the calling function as if the method had executed locally.

One of the exciting features about .NET Remoting is that this complexity can be completely masked from the developer. If everything is configured correctly a programmer can create a remote object stub simply by calling the New( ) (or comparable) constructor on a remote object. The .NET Remoting framework will generate a stub reference and return it in place of the actual object. Although the developer can step in and micromanage the remoting process if necessary, the .NET handles most common cases so well that the process is relatively painless.

Although the runtime Remoting Architecture makes it easy to create references to remote objects, you should use them judiciously. Your software incurs a performance hit each time you cross an application boundary. Make sure you keep this in mind when designing remote API for your application. For example, see if you can consolidate multiple calls to remote accessors into a single call to a more coarse-grained method.

Object Activation and State

Before you can begin instantiating and using remote objects, you need to let the .NET know about the remote object's activation and state. You should specify whether the client or the server will be responsible for the object's activation (creation, persistence, and destruction), be it server-activated or client-activated, and state. In the case of client-activated objects, you must also be wary of remote object leases.

Server-Activated Objects

Server-activated objects are objects whose life cycles are controlled exclusively by the server. Although clients can hold references to server-activated objects, the server only creates instances of these objects when one of their methods is called. Even though a client might create a stub object by calling New( ) or Activator.GetObject( ), the object does not yet need to be instantiated on the server. This "lazy loading" of server-activated objects conserves server resources and removes the need to make a network round-trip just to create the object's stub in the client. By default, server-activated objects only support default constructors (that is, constructors that don't take any arguments). Programmers must publish other constructors programmatically.

Server-activated objects come in two flavors: Singleton and SingletonCall. Singleton type objects never have more than one instance running on the server at a time. All requests to the server are serviced by that single instance. If no instance of the singleton object is in memory (for example, the first time one of its methods is called), the server creates a new instance and then services the request. The server is free to destroy a singleton object at any time as long as it creates a new one of the same type the next time it's requested. This means that the actual object the client stub points to might change over time. Because of this, singleton objects are, by definition, stateless. Singleton methods can declare local variables that will be unique for the duration of the request. However, any instance properties of the class will be shared across all clients or will be discarded if the object's instance is destroyed. Therefore, all client-specific states must be kept on the client side and passed to the singleton object with each method request.

SingletonCall type objects always have one instance on the server for each request. All requests to a SingletonCall type object will be serviced by a unique instance of the class. Subsequent requests are not guaranteed to be serviced by the same instance, however.

The following piece of code is an example of how a client can construct a server-activated object using the Activator.GetObject( ) method.

 RemoteObjectClass MyRemoteClass = (RemoteObjectClass)Activator.GetObject( typeof(RemoteObjectClass), "tcp://computername:8080/RemoteObjectUri " ); 

Now that the client has a reference to the MyRemoteClass object, it can begin invoking its methods directly.

Client-Activated Objects

As the name implies, client-activated objects have life cycles that are controlled by the client application. This paradigm is similar to the way local objects work. The server creates a unique instance of the object every time a client calls its constructor. This means that the same client application can hold references to several unique instances of a server-side object.

Client-activated objects maintain much more state than their server-activated counterparts because of the one-to-one mapping of client-side object stubs to server-side object instances. Client-activated objects behave the same way that locally instantiated objects do. Maintaining object state across a network is a difficult task. Fortunately, the .NET Framework takes complexity behind remote procedure calls and state maintenance out of the developer's list of details to worry about.

Client-activated objects have a greater potential impact on server resources than do server-activated objects. A client can create any number of instances of these objects. Stale object pointers can clutter the server with useless object instances, and distributed garbage collection is a difficult problem to solve. How does the server know when the client is finished using an object? Should it wait until the client releases its last reference to the object? Should the server try to communicate with the client periodically to see if it can reclaim the memory? These solutions are tricky to implement, particularly when network problems can arise at any moment to interfere with host-to-client communication. The .NET implements distributed garbage collection by using a lifetime lease strategy.

Remote Object Leases

When a client creates a new instance of a remote object, it must specify how long it intends to use it. Once the agreed lease duration has expired the server will contact the client and ask if it needs to renew the lease. If the client renews, everything is business as usual. If the client does not respond, the server waits a predetermined amount of time to see if the client wakes up. If the server does not hear from the client it assumes the object is no longer needed and reclaims the object's resources.

Leases implement the ILease interface that prescribes the properties and methods associated with leasing and lease renewal. Clients need not wait for the lease to expire before renewing; each call to a remote method can renew the lease. Clients can also call the Renew method synchronously to extend its life. A lease manager running on the server maintains a queue of clients that have requested leases. The manager monitors the queue and prompts clients to renew when their leases have expired.

The ILease interface is straightforward and contains only a few properties and methods. The leasing manager's queue contains a list of objects that implement this interface. Table 8-2 and Table 8-3 offer a more detailed definition of the leasing interface.

Table 8-2 ILease Public Instance Properties

Property Description

CurrentLeaseTime

Gets the amount of time remaining in the lease.

CurrentState

Gets the current leaseState of the lease.

InitialLeaseTime

Gets or sets the initial time for the lease.

RenewalOnCallTime

Gets or sets the amount of time by which a call to the remote object increases the leaseTime.

SponsorshipTimeout

Gets or sets the amount of time to wait for a sponsor to return with a lease renewal time.

Table 8-3 ILease Public Instance Methods

Method Description

Register

Overloaded. Registers a sponsor (client) for the lease.

Renew

Renews a lease for the specified time.

Unregister

Removes a sponsor from the sponsor list.

The leaseState property can take on one of the following states: Active (the lease is active and has not expired), Expired (the lease has expired and cannot be renewed), Initial (the lease has been created but is not yet active), Null (the lease is not initialized), and Renewing (the lease has expired and is looking for sponsorship).

The downside to leasing is that it is not as efficient as reference counting, the preferred mechanism for in-process garbage collection. Sometimes leases keep objects alive on the server even after the client has discarded the reference. Nonetheless, a well-managed leasing system is much cleaner to implement over error-prone networks and, over the long term, is almost as efficient as reference counting or pinging.

Configuration

Now that you understand the basic concepts behind client-activated objects, server-activated objects, and leasing, you are almost ready to write some code that uses .NET Remoting. One additional conceptual barrier stands in our way, however. How do clients discover remote objects and their properties? How is remote object metadata passed from server to client and what does that metadata describe?

First let's look at the metadata the client and server programs need to share objects. The following pieces of information are necessary to create and invoke remote methods.

  • The type of activation required. This specifies whether or not the object is client-activated or server-activated.
  • The complete metadata describing the object. The class's metadata includes a list of its public properties and types and a list of public method signatures.
  • The channel registered to handle requests for the object. This means the protocol and port number to which the remote object is bound.
  • The URI that uniquely identifies an object of that type. These last two pieces of metadata can be seen in the following example:
  • tcp://myserver.com:8080/remoteObjects/MyObject.
  • where tcp://myserver.com:8080 is the channel identifier and
    /remoteObjects/MyObject
    is the URI.

Think back to the way Web Service clients work with the WSDL. The WSDL document contains all the preceding metadata. The activation method is implicitly server-activated. The class metadata is contained in the WSDL document. The channel is implicitly http, and the URI to the Web Service is also explicitly stated in the WSDL document. This information gives the .NET Remoting framework all it needs to generate the stub classes needed to make use of the Web Service.



XML Programming
XML Programming Bible
ISBN: 0764538292
EAN: 2147483647
Year: 2002
Pages: 134

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net