Key .NET Remoting Design Decisions

As much as I'd like to jump straight into the typical "Hello World" example of .NET Remoting, you need to make a few fundamental choices before you even start to implement an architecture that incorporates .NET Remoting. These choices concern the type of activation, the object lifetime, and the message format and network transport used for communication.

Activation Modes

.NET Remoting supports three types of objects:

  • SingleCall

    These stateless objects are automatically created with every method invocation and live for only the duration of that method. The client can keep and use the same reference, but every call results in the creation of a new object.

  • Client-activated

    These objects are most similar to ordinary objects. They retain state, and each client receives a separate instance.

  • Singleton

    This type of object retains state but shares it between every client. No matter how many clients connect, there is only ever one remote object instance.

The inevitable question is which activation type represents best design practices? SingleCall objects are usually ideal because they have a very low overhead. They don't consume any server resources when they aren't working, and they can easily be hosted on multiple servers with clustering because of their stateless design. They also match the "service provider" design pattern introduced in Chapter 2.

Client-activated objects, on the other hand, are often easier to program with because they resemble ordinary objects. The problem is that this false sense of familiarity can lead developers to use them in disastrous ways. Because client-activated objects retain state, for example, you might be tempted to use property procedures, member variables, and other object-oriented practices to simplify coding. Because of the nontrivial overhead required to make a network call, however, setting and retrieving properties individually can greatly slow down your application.

Singleton objects are probably the most difficult to manage properly. Because multiple clients can call methods at the same time, there is the potential for concurrency errors subtle but serious problems that occur when data is modified simultaneously. Unfortunately, concurrency errors often don't appear in development testing and are difficult to repeat and diagnose. In addition, because of their state, singleton objects can't be used in load-balancing scenarios with multiple servers. Generally, you shouldn't use a singleton object unless you need to. In some peer-to-peer scenarios in which components need to share synchronized information, for instance, singleton objects are extremely attractive. Make sure, however, that you polish your threading skills by reading Chapter 6 and Chapter 7.

Object Lifetime

Singleton and client-activated objects have state, but they can't be allowed to live forever. Consider what would happen if a client were to forget to release the object or just disappear from view due to network problems. In these cases, the server-side objects they created would linger on in a useless zombie state, wasting valuable server resources. Multiplied by hundreds of clients over the period of several days, the server might be choked to a standstill by memory that was never properly released.

Clearly, a distributed component technology needs to take this danger into consideration. In .NET, this problem is dealt with using a lifetime leasing scheme. Essentially it works like this: An object is allowed to exist only for a fixed amount of time. If it needs to last longer, someone needs to renew its lease. This "someone" can be a dedicated lease sponsor, the client component, or the remote component itself. To ensure long-time stability and scalability of your system, however, you must implement a realistic, conservative leasing policy (as discussed a little later in this chapter).

Note

Lifetime leasing is a dramatic departure from DCOM, which uses keep-alive pinging (euphemistically known as distributed garbage collection) to manage object lifetime. Essentially, as soon as the pinging stops, the server assumes that the client had been disconnected and releases the object. The serious drawback to this technique is that the pinging is inherently unscalable in a large distributed system. Having hundreds of clients pinging remote components at the same time can significantly reduce network bandwidth and performance.


Server and Client Activation

To further complicate matters, singleton and SingleCall objects are both categorized as server-activated objects. The terms server-activated object (SAO) and client-activated object (CAO) turn up in the MSDN documentation and various publications. They cause a great deal of confusion.

For example, it's sometimes mistakenly said that lifetime leases apply only to client-activated objects, not server-activated objects. This just isn't true. Lifetime leases apply to both client-activated and singleton objects.

The real distinction between client-activated and server-activated objects is that a server-activated object isn't really created when a client instantiates it. Instead, it is created as needed. If the object is a SingleCall object or a singleton that doesn't exist yet, it's created with the first method call. Client-activated objects, on the other hand, are created when the client instantiates them.

Why is this distinction important? The difference is minor, except for one detail: client-activated objects can use parameterized constructors. Server-activated objects can be created only with the default (no parameter) constructor because they're not created directly by the client they're created indirectly by the server.

Communication

The final decision you need to make when implementing a remote component is the communication format and transport to use. Although .NET uses a pluggable format that allows any type of formatter or channel, by default the .NET Framework ships with two formatters and two channels. These prebuilt choices serve most needs.

You can choose from two formatters:

  • Binary Formatter

    The Binary Formatter serializes data to a compact, proprietary .NET format (although it doesn't compress the data). This formatter offers the best performance but can be used only by .NET applications.

  • SOAP Formatter

    The SOAP Formatter serializes data to a SOAP message, which is a cross-platform XML-based plain-text format. Because clients on other platforms can create and send SOAP messages, this formatter can allow cross-platform communication with a remote .NET component. The SOAP format requires larger message sizes, however, and can therefore reduce overall performance. To get around this limitation, you can use the Binary Formatter or create objects that implement custom serialization. For example, the DataSet is an example of a class that uses custom serialization to optimize performance it encodes its content into binary data, which is then inserted into the SOAP message.

There are also two channels:

  • TcpChannel

    This channel uses the connection-based TCP protocol. It's ideal for internal networks.

  • HttpChannel

    This channel uses the HTTP protocol, which is ideal for scenarios in which you need to communicate across the Internet. HTTP is based on the TCP/IP protocol, but it doesn't require a continuous connection. Instead, it communicates using request and response messages.

When defining a channel, you also need to choose a port number for the communication. Essentially, to communicate with a remote object you need the machine name (or IP address) and a port number (from 0 through 65,535) that maps to a network service and specific application. Choosing the correct port in a production environment might require some consultation with a network or firewall administrator in your organization. However, there are several rules of thumb:

  • Ports 0 to 1023 are well-known ports and are often used by system services. All Web browsers connect to port 80 by default for HTTP. In general, you shouldn't use these ports for your applications.

  • Ports 1024 to 41,9151 are registered ports that are available for use on most systems.

  • Ports 49152 to 65,535 are dynamic or private ports.

I've actually simplified the issue slightly. When creating a connection, you have the choice of creating dedicated client and server channels, or bidirectional channels. With a dedicated client-server channel, the client invokes methods and the server returns information. However, the server can't invoke a method of the client object or raise an event to the client.

You can see all the prebuilt channels in the machine.config file (which is stored in the directory C:\[WinDir]\Microsoft.NET\Framework\[Version]\CONFIG). Each channel is given a friendly id attribute (which is the name you use in your configuration files) and more specific information about the underlying class, assembly, and version, as shown in Listing 4-4.

Listing 4-4 Channel templates in the machine.config file
 <channels>     <channel            type="System.Runtime.Remoting.Channels.Http.HttpChannel,                System.Runtime.Remoting, Version=1.0.3300.0,                 Culture=neutral, PublicKeyToken=b77a5c561934e089"/>     <channel            type="System.Runtime.Remoting.Channels.Http.HttpClientChannel,                System.Runtime.Remoting, Version=1.0.3300.0,                Culture=neutral, PublicKeyToken=b77a5c561934e089"/>     <channel            type="System.Runtime.Remoting.Channels.Http.HttpServerChannel,                System.Runtime.Remoting, Version=1.0.3300.0,                Culture=neutral, PublicKeyToken=b77a5c561934e089"/>     <channel           type="System.Runtime.Remoting.Channels.Tcp.TcpChannel,                System.Runtime.Remoting, Version=1.0.3300.0,                Culture=neutral, PublicKeyToken=b77a5c561934e089"/>     <channel           type="System.Runtime.Remoting.Channels.Tcp.TcpClientChannel,                System.Runtime.Remoting, Version=1.0.3300.0,                Culture=neutral, PublicKeyToken=b77a5c561934e089"/>     <channel           type="System.Runtime.Remoting.Channels.Tcp.TcpServerChannel,                System.Runtime.Remoting, Version=1.0.3300.0,                Culture=neutral, PublicKeyToken=b77a5c561934e089"/> </channels> 

If you want to, you can add your own defaults to the machine.config file. Doing so enables you, for example, to register a channel that always uses a certain port. However, these changes must then be applied to the machine.config file in every user's computer, which can be a tedious (and even risky) process.

Note

The .NET Framework also provides lower-level classes that enable you to create socket-based connections or send information over HTTP, FTP, or UDP manually. (See, for example, the System.Net and System.Net.Sockets namespaces.) These classes allow a great deal of flexibility and are probably required if you need optimum performance in a complicated peer-to-peer application (such as a multiplayer networked computer game). However, it's much less common to develop enterprise applications with these classes, both because it requires a good deal more code and because it can easily introduce unexpected vulnerabilities or unnoticed errors. It's also much less likely if you need to interoperate with components hosted on other platforms, languages, or operating systems. When designing distributed applications, you'll generally want to use the higher-level .NET Remoting Framework (or XML Web services) and concentrate on optimizing the database and network architecture instead of reinventing the wheel with custom networking code.




Microsoft. NET Distributed Applications(c) Integrating XML Web Services and. NET Remoting
MicrosoftВ® .NET Distributed Applications: Integrating XML Web Services and .NET Remoting (Pro-Developer)
ISBN: 0735619336
EAN: 2147483647
Year: 2005
Pages: 174

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