Remoting Overview


It’s important to understand several basics about remoting, including the basic terms and related objects, which are covered in the following sections.

Basic Terminology

A normal object is not accessible via remoting. By default, .NET objects are only accessible to other code running within the same .NET AppDomain.

A remote object is an object that’s been made available over remoting by inheriting from System.MarshalByRefObject. These objects are often also called MBROs. Remote objects are the same kinds of objects that you build normally, but they inherit from MarshalByRefObject and you must register them with the Remoting subsystem to make them available to clients. They are anchored to the machine and AppDomain where they were created, and you communicate with them over the network. The wonderful aspect of this situation is that the client is working with a proxy object, instantiated by the client, that allows programmatic access to the remote object just as if it were in the same process as your client application, even though it actually resides in a completely separate process - even on a completely separate machine.

A serializable object is an object that’s been made available over remoting by marking the class with the <Serializable()> attribute. These objects move from machine to machine or AppDomain to AppDomain. They are not attached to any particular location, so they are unanchored objects. A common example of a serializable object is the DataSet, which can be returned from a server to a client across the network. The DataSet physically moves from server to client via the serialization technology in the .NET Framework.

A remoting host is a server application that configures remoting to listen for client requests. Remoting runs within the host process, using the memory and threads of the host process to handle any client requests. The most common remoting host is IIS. You can create custom remoting hosts, which are typically created as a Windows Service, so they can run even when no user is logged in to the server. It is also possible to have any .NET application be a remoting host, which enables you to emulate ActiveX EXE behaviors to some degree. This last technique is most commonly used when creating peer-to-peer-style applications.

A channel is a way of communicating between two machines. In order for two separate application processes to communicate with each other, a transport channel is opened between the processes. A transport channel is a combination of underlying technologies required to open a network connection and use a particular protocol to send the bytes to the receiving application. .NET includes two channels: TCP and HTTP. A channel works with a stream of data and creates an object based upon the transport protocol. The TCP channel is a lightweight channel designed for transporting binary data between two computers. (The TCP channel is different from the TCP protocol that HTTP also uses.) It works using sockets, discussed in much more detail in Chapter 29. TCP is better suited for an intranet environment because an intranet sits behind a firewall, and TCP does not always cross firewalls easily. Using TCP also means that a binary formatter is used by default, which actually reduces the size of the object being transported. Having smaller packages to transport allows for better and faster network communications.

HTTP, as you already know, is the protocol that Web servers use. The HTTP channel hosted in IIS is the recommended approach by Microsoft. HTTP is a firewall-friendly transport because HTTP traffic generally flows directly through firewalls over port 80 (which is generally open on most computers).

After a channel is established through a specific port, a formatter object is needed to initiate the serialization or deserialization of the object. A formatter object serializes or marshals an object’s data into a format in which it can be transferred down the channel. In order for an object to move through the channel from one process to another, the formatter must take the object that you are sending and serialize it into the network stream. Out of the box, you have two formatter objects: BinaryFormatter and SoapFormatter. The BinaryFormatter is more efficient and is recommended. The SoapFormatter is not recommended and may be discontinued in future versions of the .NET Framework.

A message is a communication between the client and server. It holds the information about the remote object and the method or property that’s being invoked, as well as any parameters.

A proxy is used on the client side to call into the remote object. To use remoting, you don’t typically have to worry about creating the proxy - .NET can do it for you. However, there’s a slightly confusing split between something called a transparent proxy and a real proxy. A transparent proxy is so called because “you can’t see it.” When you request a remote object, a transparent proxy is what you get. It looks like the remote object (that is, it has the same properties and methods as the original). This means that your client code can use the remote object or a local copy of the object without your having to make any changes and without your knowing there is any difference. The transparent proxy defers the calls to the real proxy. The real proxy is what actually constructs the message, sends it to the server, and waits for the response. You can think of the transparent proxy as a “fake” object that contains the same methods and properties that the real object contains.

The real proxy is effectively a set of helper functions that manages the communications. You don’t use the real proxy directly; instead, the transparent proxy calls into the real proxy on your behalf.

A message sink is an “interceptor object.” Before messages go into the channel, these are used to do some further processing on them, perhaps to attach more data, to reformat data before it is sent, for route debugging information, or to perform security checking. On the client side, you have an envoy sink. On the server side, you have a server context sink and an object context sink. In typical use, you can ignore these.

Message sinks are a pretty advanced topic and allow for some powerful extensions to the remoting model. It is not recommended that you create custom sinks, channels, or formatters, so they are not covered in this book. Creating them is not recommended because they will not transfer directly to WCF, the next generation of the technology from Microsoft. If you do opt to create your own custom sink, formatter, or channel, expect to rewrite it from scratch when you upgrade to WCF.

Figures 27-1 and 27-2 show how these concepts fit together.

image from book
Figure 27-1

image from book
Figure 27-2

Figure 27-1 shows how a client calls the Hello() method of a transparent proxy object. The transparent proxy looks just like the real object, so the client doesn’t even realize that remoting is involved. The transparent proxy then invokes the real proxy, which converts the method call into a generic remoting message.

This message is sent through any messaging sinks configured on the client. These messaging sinks may transform the message in various ways, including adding encryption or compressing the data. The message is then serialized by the formatter object. The result is a byte stream that is sent to the server by using the channel configured for use on the client.

Figure 27-2 shows how the server handles the message. The message comes into the server via a channel. The message is then deserialized by the formatter object and run through any messaging sinks configured on the server. These messaging sinks typically mirror those on the client, unencrypting or decompressing the data as appropriate.

Finally, the message is decoded by the object context sink, which uses the information in the message to invoke the method on the actual object. The object itself has no idea that it was invoked via remoting, as the method call was merely relayed from the client.

SingleCall, Singleton, and Activated Objects

In remoting, objects are divided into three camps: wellknown objects, client-activated objects, and serializable objects.

  • The wellknown objects run on the server and perform a service for the remote application, such as give me a list of all the customers or create an invoice. They can be configured to act similarly to a Web Service or to use what’s called a singleton pattern (which is discussed shortly).

  • Client-activated (Activated) objects are created for each client and maintain state on the server over time. In many ways, these objects act similarly to COM objects you may have accessed via DCOM in the past.

  • Serializable objects can move from machine to machine as needed. For instance, a serializable object can be created on the server (by a wellknown or Activated object), and then returned to a client. When the object is returned to the client, it is physically copied to the client machine, where it can be used by client code.

The following table summarizes the types of object:

Open table as spreadsheet

Type

Calling Semantics

Key Attributes

SingleCall (wellknown)

An object is created for each client method call made to the server.

Stateless, per-method lifetime, atomic methods, no threading issues, anchored to AppDomain where created.

Singleton (wellknown)

One object exists on the server and is used to handle all method calls from all clients.

Stateful, long-lived, shared instance, thread synchronization required, anchored to AppDomain where created.

Activated

The client creates Activated objects on the server. The client can create many such objects. Activated objects are available only to the client that created the object.

Stateful, long-lived, per-client instances, threading issues only if client is multithreaded, anchored to AppDomain where created.

Serializable

The object is automatically copied from machine to machine when it is passed as a parameter or returned as the result of a function.

Stateful, long-lived, no threading issues, non-anchored (moves across network automatically).

SingleCall Objects

SingleCall objects act much like typical Web Service objects. Each time a client calls a method on a SingleCall object, an object is created specifically to handle that method call. Once the method call is complete, the object is not reused and is garbage collected by the .NET runtime.

SingleCall objects also work the way a JIT (just-in-time) Activated object does in COM+, and match the way most people use MTS or COM+ objects. In those environments, good developers typically create a server-side object, make a method call, and then release the object.

These objects must inherit from System.MarshalByRefObject, so they are MBROs. This means that they always run in the AppDomain and Windows process where they are created. If they are created on a server in a host process, that is where they live and run. Clients interact with them across the network.

The most commonly used type of service object in remoting is the SingleCall object. Not only do these objects provide semantics similar to Web Services, MTS, and COM+, but they also provide the simplest programming model.

Because an object is created for each method call, these objects are inherently stateless. Even if an object tried to keep state between calls, it would fail because the object is destroyed after each method is complete. This helps ensure that no method call can be affected by previous method calls or contaminate subsequent method calls.

Each method call runs on its own thread (from the .NET thread pool, as discussed in Chapter 24). However, because each method call also gets its very own object, there’s typically no contention between threads, so you don’t need to worry about writing synchronization or locking code in your SingleCall code.

Tip 

Technically, it is possible to encounter synchronization issues if there are shared stateful objects on the server. It requires substantial work to create and access such shared objects and is not covered in this book. Typically, this type of model is not used, so threading is a non-issue with SingleCall objects.

Because of their automatic isolation, statelessness, and threading simplicity, SingleCall objects are the preferred technology for creation of server code in remoting.

Singleton Objects

Singleton objects are quite different from SingleCall objects. Only one Singleton object exists at a time, and it may exist for a long time and maintain state. All client method calls from all users are routed to this one Singleton object. This means that all clients have equal, shared access to any state maintained by the Singleton object.

These objects must inherit from System.MarshalByRefObject, so they are MBROs. This means that they always run in the AppDomain and Windows process where they are created. If they are created on a server in a host process, that is where they live and run. Clients interact with them across the network.

As with the SingleCall scenario, all method calls are run on threads from the .NET thread pool, which means multiple simultaneous method calls can be running on different threads at the same time. As discussed in Chapter 24, this can be complex, as you have to write multithreaded synchronization code to ensure that these threads don’t collide as they interact with your Singleton object.

Singleton objects have a potentially unpredictable life span. When the first client makes the first method call to the object, it is created. From that point forward, it remains in memory for an indeterminate period of time. As long as it remains in memory, all method calls from all the clients are handled by this one object. However, if the object is idle for a long time, remoting may release it to conserve resources. In addition, some remoting hosts may recycle their AppDomain objects, which automatically causes the destruction of all your objects. Therefore, you can never be certain that the data stored in memory in the object will remain available over time. This means that any long-term state data must be written to a persistent store like a database.

Due to the complexity of shared memory, thread synchronization, and dealing with object lifetime issues, Singleton objects are more complex to design and code than SingleCall objects. While they can be useful in specialized scenarios, they aren’t as widely used as SingleCall objects.

Activated Objects

Client-activated (or Activated) objects are different from both SingleCall and Singleton objects. Activated objects are created by a client application, and they remain in memory on the server over time. They are associated with just that one client, so they are not shared between clients. They are state-ful objects, meaning they can maintain data in memory during their lifetime.

These objects must inherit from System.MarshalByRefObject, so they are MBROs. This means that they always run in the AppDomain and Windows process where they are created. If they are created on a server in a host process, that is where they live and run. Clients interact with them across the network.

A client can create multiple Activated objects on the server. The objects remain on the server until the client releases the objects or the server Appdomain is reset (which can happen with some types of remoting host). If the client doesn’t contact the server for several minutes, then the server assumes the client abandoned the objects and it releases them.

Activated objects typically don’t have any threading issues. The only way multiple threads will run in the same Activated object is if the client is multithreaded, and multiple client threads simultaneously make method calls to the same server-side Activated object. If this is the case in your application, then you’ll have to deal with shared data and synchronization issues, discussed in Chapter 24.

While long-lived, stateful, per-client objects can be useful in some specialized scenarios, they are not commonly used in most client/server or n-tier application environments. Storing per-client state in an object on the server reduces the scalability and fault tolerance of a system.

Serializable Objects

While SingleCall, Singleton, and Activated objects are always anchored to the Appdomain, Windows process, and machine where they are created, this is not the case with Serializable objects.

Serializable objects can move from machine to machine as needed. The classic example of this is the ADO.NET DataSet, which can be returned as a result of a function on a server. The DataSet physically moves to the client machine, where it can be used by client code. When the client wants to update the DataSet, it simply passes the object to the server as a parameter, causing the DataSet to physically move to the server machine.

These objects do not inherit from System.MarshalByRefObject. Instead, they are decorated with the <Serializable()> attribute and may optionally implement the ISerializable interface. The following is a very basic implementation of a <Serializable()> object:

 <Serializable()> _ Public Class Customer   Private mName As String = ""   Public Property Name() As String     Get       Return mName     End Get     Set(ByVal value As String)       mName = value     End Set     Public Sub Load()       ' Load data here.     End Sub End Class

<Serializable()> objects are not anchored to the Appdomain or Windows process where they were created. The remoting subsystem automatically serializes these objects’ data and transfers it across the network to another machine. On that other machine, a new instance of the objects is created and loaded with the data, effectively cloning the objects across the network.

When working with serializable objects, it’s typically a good idea to use a SingleCall object on the server to create the Serializable object and call any server-side methods (such as those to load the object with data from a database). The SingleCall object then returns the serializable object to the client as a function result so the client can interact with the object. The SingleCall object’s method might look like this:

 Public Function GetCustomer(ByVal ID As Integer) As Customer   Dim cust As New Customer()   cust.Load(ID)   Return cust End Function

The client code might look like this:

 Dim cust As Customer cust = myService.GetCustomer(123) TextBox1.Text = cust.Name()

Note that both server and client code have direct, local access to the Customer object because it is automatically copied from the server to the client as a result of the GetCustomer() method call.

Serializable objects can be very useful in many client/server scenarios, especially if the application is created using object-oriented application design principles.




Professional VB 2005 with. NET 3. 0
Professional VB 2005 with .NET 3.0 (Programmer to Programmer)
ISBN: 0470124709
EAN: 2147483647
Year: 2004
Pages: 267

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