Chapter 11 — Improving Remoting Performance

 

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

Improving .NET Application Performance and Scalability

J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman
Microsoft Corporation

May 2004

Related Links

Home Page for Improving .NET Application Performance and Scalability

Chapter 5, Improving Managed Code Performance

Checklist: Remoting Performance

Send feedback to Scale@microsoft.com

patterns & practices Library

Summary: This chapter presents concrete recommendations for when to use remoting and when not to use it, together with appropriate alternatives. The design guidelines and coding techniques in this chapter provide performance solutions for activation, channels, formatters, and serialization.

Contents

Objectives
Overview
How to Use This Chapter
Architecture
Prescriptive Guidance for Choosing Web Services, Enterprise Services, and .NET Remoting
Performance and Scalability Issues
Design Considerations
Implementation Considerations
Activation
Lifetime Considerations
Hosts
Channels
Formatters
MarshalByRef vs. MarshalByValue
Serialization and Marshaling
DataSets and Remoting
Summary
Additional Resources

Objectives

  • Identify remoting performance issues.
  • Optimize .NET remoting solutions for performance.
  • Choose the appropriate host, channel, and formatter combination.
  • Choose an appropriate activation model.
  • Evaluate and choose the most appropriate object lifetime strategy.
  • Evaluate and choose the most appropriate state management strategy.
  • Improve serialization performance.

Overview

.NET remoting is the preferred communication mechanism for single process, cross application domain communication. For crossing process or server boundaries or where communication is required across deployment or trust boundaries, Web services are the recommended option.

Factors that have a significant impact on .NET remoting performance include the choice of channel and formatter, interface design, marshaling, the object activation model, and state management. This chapter discusses these and other remoting performance issues, and provides recommendations that will help you use remoting efficiently.

This chapter starts by providing a brief overview of .NET remoting architecture and introducing the main concepts and terminology. It then provides prescriptive guidance to help you choose the appropriate communication technology for your particular scenario. This chapter then presents a series of design considerations, followed by implementation considerations and recommendations that will help you build efficient .NET remoting solutions.

How to Use This Chapter

Use this chapter to identify remoting performance issues and to learn key design considerations for .NET remoting solutions. To get the most out of this chapter, do the following:

  • Jump to topics or read from beginning to end. The main headings in this chapter help you locate the topics that interest you. Alternatively, you can read this chapter from beginning to end to gain a thorough appreciation of performance and scalability design issues.
  • Use the checklist. Use the "Checklist: Remoting Performance" checklist in the "Checklists" section of this guide to quickly view and evaluate the guidelines presented in this chapter.
  • Use the "Architecture" section of this chapter. This section helps you understand how remoting works. By understanding the architecture, you can make better design and implementation choices.
  • Use the "Design Considerations" section of this chapter. This section helps you understand the higher level decisions that will affect implementation choices for remoting code.
  • Read Chapter 13, "Code Review: .NET Application Performance" See the "Remoting" section for specific guidance.
  • Measure your application performance. Read the "Remoting" and ".NET Framework Technologies" sections of Chapter 15, "Measuring .NET Application Performance" to learn about the key metrics that can be used to measure application performance. It is important for you to measure application performance so that you can accurately identify and resolve performance issues.
  • Test your application performance. Read Chapter 16, "Testing .NET Application Performance" to learn how to apply performance testing to your application. It is important to apply a coherent testing process and to analyze the results.
  • Tune your application performance. Read Chapter 17, "Tuning .NET Application Performance" to learn how to resolve performance issues identified through the use of tuning metrics.

Architecture

.NET remoting uses channels to communicate method calls between two objects in different application domains (AppDomains). Channels rely on formatters to create a wire representation of the data being exchanged. The following list briefly outlines the main components of the .NET remoting infrastructure:

  • Channels. .NET remoting provides two channel implementations:
    • HttpChannel
    • TcpChannel
  • Formatters. Each channel uses a different formatter to encode data on the wire. Two formatters are supplied:
    • BinaryFormatter. This uses a native binary representation.
    • SoapFormatter. This uses XML-encoded SOAP as the message format.
  • Sinks. The .NET remoting infrastructure supports an extensibility point called a sink. The BinaryFormatter and SoapFormatter classes are examples of system-provided sinks. You can create custom sinks to perform tasks such as data compression or encryption.
  • Proxy. Clients communicate with remote objects through a reference to a proxy object. The proxy is the representation of the remote object in the local application domain. The proxy shields the client from the underlying complexity of marshaling and remote communication protocols.
  • Host. This is the process that hosts the remoting endpoint. Possible hosts include Internet Information Services (IIS) or custom executables such as a Windows service. The choice of host affects the type of channel that can be used to communicate with the remote object. Possible hosts include:
    • A Windows service application.
    • IIS and ASP.NET.
    • A Windows application.
    • A console application.

Figure 11.1 shows the main elements of the .NET remoting infrastructure.

Ff647782.ch11-net-remoting-architecture(en-us,PandP.10).gif

Figure 11.1: .NET remoting architecture

Activation

A remotable type must be created and initialized before it can be accessed. This process is referred to as activation. .NET remoting supports two types of activation: serveractivation and clientactivation.

Server-Activated Objects

Server-activated objects (SAOs) are created at the server by one of two activation models:

  • Singleton. A single object instance services all client requests. Singletons guarantee that only one object instance is in memory at any time per application domain.
  • Singlecall. Each client call is serviced by a new object instance. No state management is provided by this model. This model is well suited for load balancing and increased scalability.

Client-Activated Objects

Client-activated objects (CAOs) are created on the server and initiated by the client. A new instance is created for each client call to new or Activator.CreateInstance. CAOs can be stateful.

Object Lifetime

Regardless of activation type, all remotable objects can be destroyed and freed from memory by the server. This is by design and allows the server to reclaim resources that are no longer in use or active. You can fine-tune the object lifetime semantics to meet the needs of your application and prevent the server from destroying or freeing an object from memory. For more information, see "Lifetime Considerations" later in this chapter.

Prescriptive Guidance for Web Services, Enterprise Services, and .NET Remoting

Services are the preferred communication technique to use across application boundaries, including platform, deployment, and trust boundaries. You can implement services today by using Web services or Web Services Enhancements (WSE). Although WSE provides a rich set of features, you should evaluate whether or not you can accept the WSE support policy. Enterprise Services provides component services such as object pooling, queued components, a role-based security model and distributed transactions, and should be used as an implementation detail within your service when you need those features. .NET remoting is preferred for cross-application communication within the same process.

Object Orientation and Service Orientation

When you design distributed applications, use the services approach whenever possible. Although object orientation provides a pure view of what a system should look like and is effective for producing logical models, an object-based approach can fail to consider real-world factors, such as physical distribution, trust boundaries, and network communication, as well as nonfunctional requirements, such as performance and security.

Table 11.1 summarizes some key differences between object orientation and service orientation:

Table 11.1   Object Orientation vs. Service Orientation

Object Orientation Service Orientation
Assumes a homogeneous platform and execution environment. Assumes a heterogeneous platform and execution environment.
Shares types, not schemas. Shares schemas, not types.
Assumes cheap, transparent communication. Assumes variable cost, explicit communication.
Objects are linked: object identity and lifetime are maintained by the infrastructure. Services are autonomous: security and failure isolation are a must.
Typically requires synchronized deployment of both client and server. Allows continuous, separate deployment of client and server.
Is easy to conceptualize and thus provides a natural model to follow. Builds on ideas from component software and distributed objects. Dominant theme is to manage/reduce sharing between services.
Provides no explicit guidelines for state management and ownership. Owns and maintains state or uses the reference state.
Assumes a predictable sequence, timeframe, and outcome of invocations. Assumes message-oriented, potentially asynchronous, and long-running communications.
Goal is to transparently use functions and types remotely. Goal is to provide inter-service isolation and wire interoperability based on standards.

Application Boundaries

Common application boundaries include platform, deployment, trust, and evolution. (Evolution refers to whether or not you develop and upgrade applications together.) When you evaluate architecture and design decisions that affect your application boundaries, consider the following:

  • Objects and remote procedure calls (RPC) are appropriate within boundaries.
  • Services are appropriate across and within boundaries.

Recommendations for Web Services, Enterprise Services, and .NET Remoting

When you are working with ASP.NET Web services, Enterprise Services, and .NET remoting, Microsoft recommends that you:

  • Build services using ASP.NET Web services.
  • Enhance your ASP.NET Web services with WSE if you need the WSE feature set and you can accept the support policy.
  • Use object technology, such as Enterprise Services or .NET remoting, within a service implementation.
  • Use Enterprise Services inside your service boundaries for the following scenarios:
    • You need the Enterprise Services feature set (such as object pooling; declarative, distributed transactions; role-based security; and queued components).
    • You are communicating between components on a local server and you have performance issues with ASP.NET Web services or WSE.
  • Use .NET remoting inside your service boundaries in the following scenarios:
    • You need in-process, cross-application domain communication. Remoting has been optimized to pass calls between application domains extremely efficiently.
    • You need to support custom wire protocols. Understand, however, that this customization will not port cleanly to future Microsoft implementations.

Caveats

When you work with ASP.NET Web services, Enterprise Services, or .NET remoting, consider the following caveats:

  • If you use ASP.NET Web services, avoid or abstract your use of low-level extensibility features such as the HTTP Context object.
  • If you use .NET remoting, avoid or abstract your use of low-level extensibility such as .NET remoting sinks and custom channels.
  • If you use Enterprise Services, avoid passing object references inside Enterprise Services. Also, do not use COM+ APIs. Instead, use types from the System.EnterpriseServices namespace.

More Information

For more information, see the following resources:

Performance and Scalability Issues

This section summarizes the main issues that can adversely affect the performance and scalability of .NET remoting. Subsequent sections in this chapter provide strategies and technical information to prevent or resolve each of these issues. There are several main performance and scalability issues:

  • Wrong channel type. If you select the wrong channel, you limit the type of host that can service method calls. The wrong channel can also limit the ability to load balance requests across a group of servers.
  • Incorrect formatter. Parameter data and return values must be converted by the formatter so they can be passed across the remoting boundary. If you select the wrong formatter, you can increase the amount of data being transmitted and seriously decrease performance and scalability.
  • Wrong activation type. Remote objects can be activated by the server or by the client. The activation method affects the lifetime, concurrency, state management, scalability, and performance of the system.
  • Chatty interfaces. Chatty interfaces result in multiple round trips to perform a single, logical operation. You can significantly improve performance by reducing round trips.
  • Resource affinity. Anything that causes a method call to be serviced by a specific computer, process, CPU, thread, or object reduces your application's ability to scale up or out.
  • Object lifetime. Objects that live for long periods of time on the server can be useful for state management scenarios. However, these objects often cause resource affinity and adversely affect scalability. Accurately controlling object lifetime can increase performance and scalability.
  • State management. Implementing state in remote components can introduce affinity issues, increase the latency of request execution, and contribute to resource pressure on the server. Generally, you should prefer stateless components and store state in a database for reasons of scalability, security, and design simplicity.
  • Inefficient data types. Returning a DataSet object that contains a single row with a single column value is very expensive when a value type is all that is needed. It is important that you use the most efficient data type with remoting.
  • Blocking operations. The thread that handles a remoting request is blocked from servicing additional requests while the thread is waiting for a downstream call to return. Calls to stored procedures and other network calls can block the thread for a significant amount of time.

Design Considerations

To help ensure that .NET remoting is optimized for performance, there are a number of issues that you must consider, and a number of decisions that you must make at design time. This section summarizes the major considerations:

  • Use .NET remoting for communicating between application domains in the same process.
  • Choose the right host.
  • Choose the right activation model.
  • Choose the right channel.
  • Choose the right formatter.
  • Choose between synchronous or asynchronous communication.
  • Minimize round trips and avoid chatty interfaces.
  • Avoid holding state in memory.

Use .NET Remoting for Communicating between Application Domains in the Same Process

.NET remoting is appropriate for communicating between application domains within the same process, and it supports a wide range of data format and communication channel combinations. However, it does not provide the same degree of interoperability and support for Web Services Description Language (WSDL) and SOAP over HTTP as Web services.

Choose the Right Host

Choosing the right host can improve the ability to scale out the server infrastructure. You can use IIS and ASP.NET, a Windows service, or any Windows executable as a remoting host. The primary advantage of using IIS is that you can use IIS security features, such as authentication and Secure Sockets Layer (SSL). You should only consider a custom process in a trusted server environment. If you do build a custom process, use the TcpChannel for optimum performance. For more information, see "Hosts" later in this chapter.

Choose the Right Activation Model

The way an object is activated has a large impact on affinity, state management, load balancing, performance, and scalability. .NET remoting supports server-activated and client-activated objects.

  • Server-Activated Objects (SAOs). Server-activated objects (SAOs) are usually preferred, because they allow the method call from the client to be serviced by any available server that receives the request. There are two types of SAOs:
    • Singleton. In the singleton case, an object is instantiated at the server and this instance serves requests for all clients. The common language runtime (CLR) provides a thread pool to service incoming client calls. As a result, singletons that maintain shared state require synchronization code to ensure valid state management.

      **Note   **Singletons do not guarantee that the same instance is always available in memory to serve client requests. They do guarantee that there is only a single instance of that type available, at any one time, to service client requests. For ways to control a singleton's lifetime, see "Lifetime Considerations" later in this chapter.

    • SingleCall. SingleCall objects live only for the life of the method call. They cannot maintain any state because they are destroyed after servicing the method. SingleCall objects are free from synchronization code because they serve requests for only a single client before being destroyed.

  • Client-Activated Objects (CAOs). Client-activated objects (CAOs) have the benefit of making state management in the object easier to maintain. However, CAOs limit the scalability of the system. CAOs are beneficial when you are using a single server approach and opting for stateful components.

Choose the Right Channel

Choosing a channel can impact the speed of message transfer and interoperability. There are two channel types to choose from:

  • TCPChannel. This produces maximum performance for a remoting solution using the BinaryFormatter.
  • HttpChannel. Uses SOAP by default to encode payloads. Use when interoperation is important, or when communicating through a firewall.

Choose the Right Formatter

Both channels, TcpChannel and HttpChannel, can work with both the BinaryFormatter and the SoapFormatter. If speed is your primary concern, use the BinaryFormatter. The following describes both formatters:

  • BinaryFormatter. The HttpChannel defaults to the SoapFormatter. To change this default, change the following configuration information in the configuration files for your server and client application.

    • Server configuration:

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
        <system.runtime.remoting>
          <application>
            <channels>
              <channel ref="http" port="8080">
                <serverProviders>
                  <formatter ref="binary"/>
                </serverProviders>
              </channel>
           </channels>
          </application>
        </system.runtime.remoting>
      </configuration>
      
    • Client configuration:

      <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
        <system.runtime.remoting>
          <application>
            <channels>
              <channel ref="http" port="8080">
                <clientProviders>
                  <formatter ref="binary"/>
                </clientProviders>
              </channel>
           </channels>
          </application>
        </system.runtime.remoting>
      </configuration>
      
  • SoapFormatter. This is primarily used for interoperability. If you need to use SOAP for message communication, consider using Web services.

    **Note   **The SOAP format used by the SoapFormatter is not entirely interoperable and should not be considered a truly interoperable approach for cross-platform communication. Interoperability is best achieved with Web services.

Choose Between Synchronous or Asynchronous Communication

Remote calls can be invoked by using synchronous or asynchronous calls. By choosing the most appropriate remote calling method, you can increase the responsiveness of your application. When making a decision, consider the following:

  • Consider asynchronous client calls when you perform parallel tasks. If client responsiveness is an issue for Windows Forms applications, consider invoking remote method calls asynchronously rather than performing synchronous blocking calls. However, if your client is an ASP.NET application, you should be aware that invoking methods asynchronously and then blocking the calling thread to pick up return values can have a detrimental impact on the Web application and can quickly lead to thread starvation. You should use asynchronous calls in the following scenarios:
    • When you have some useful work to do after making the remote call before blocking on the main worker thread processing the requests.

      MyRemoteObj obj = new MyRemoteObj();
      
      IASyncReult ar= obj.BeginLongCall(…);
      
      //Do some useful work before blocking here
      
      Ar.AsynchWaitHandle.WaitOne();
      
    • When you need to make discrete remote calls that are not dependent on each other.

      MyRemoteObj1 obj1 = new MyRemoteObj1();
      MyRemoteObj2 obj2 = new MyRemoteObj2();
      
      IASyncReult ar1= obj1.BeginLongCall1(…);
      IASyncReult ar2 = obj2.BeginLongCall2(…);
      
      WaitHandle[] wh = {ar1.AsynchWaitHandle, ar2.AsynchWaitHandle}
      
      WaitHandle.WaitAll(wh);
      

For more information, see "Threading Guidelines" in Chapter 6, "Improving ASP.NET Performance."

  • Asynchronous remoting limitations. There are no bidirectional channels in remoting. This means that you have to configure a separate channel for callbacks. Having a firewall between the object and client leads to the opening of more ports and configuration issues.

    **Note   **Events and delegates also require the typeFilterLevel to be set to Full when using .NET Framework 1.1.

  • Consider using the OneWay attribute when you do not need return values. You can mark server object methods with the OneWay attribute. Clients that call methods marked with this attribute do not wait for the method to execute before control is returned. This can improve client performance by not having to wait for method completion at the server. OneWay methods can be called synchronously or asynchronously. In either case, the calling thread does not wait. One-way methods must not have any return values, out parameters, or raise any errors. The client cannot assume that the server successfully completed an operation. The following is an example of the OneWay attribute.

    public class HelloServer : MarshalByRefObject {
    
      public HelloServer() {}
    
      [OneWay()]
      public void SayHello() {
      Console.WriteLine(" Hello World");
      }
    }
    
  • Consider message queuing. Many applications can benefit from asynchronous message queuing. Microsoft Windows Message Queuing (also known as MSMQ) is available to .NET Framework applications. Alternatively, for object-based message queuing, Enterprise Services provides Queued Components, which also uses message queuing. Message queuing allows you to queue requests for processing when server processes are not available for processing. Clients can still receive notifications about the success or failure of an asynchronous message by processing reply messages from the server through a second notification queue. Message queuing is available to managed applications through the types in the System.Messaging namespace, while Queued Components are available through the System.EnterpriseServices namespace.

Minimize Round Trips and Avoid Chatty Interfaces

Design chunky, not chatty, interfaces to minimize round trips. Each time a remote method is invoked, this incurs data marshaling, security checks, and thread switches. All of these impact performance.

Try to reduce the number of calls used to complete a logical unit of work. The following code shows an example of calling a component, by using a chatty interface. Notice how the inefficient (chatty) interface design forces the caller to traverse the remoting boundary three times to perform the single task of saving customer details.

MyComponent.Firstname = "bob";
MyComponent.LastName = "smith";
MyComponent.SaveCustomer();

The following code shows how the same functionality should be implemented to reduce the operations and boundary crossings required to complete the single logical operation.

MyComponent.SaveCustomer( "bob", "smith");

More Information

For more information, see Knowledge Base article 322975, "BUG: Passing Large Quantities of Data in .NET Remoting Calls Causes an Unexpected Exception to Occur," at https://support.microsoft.com/default.aspx?scid=kb;en-us;322975.

Avoid Holding State in Memory

State management is a big concern for distributed application design. Poor state management choices can limit the ability to scale out the server farm, provide failover support, and limit performance.

You should use stateless components where possible. Where state must be held in memory, choose data that remains constant, such as country codes and city names.

If you activate components as singletons, they are bound to the server that they are created on. In a server farm, this presents problems because each server has a different object with its own state. This affects your application's ability to scale out and failover. By designing stateless components, you can use singleton-activated components in a farm; this may outperform single-call activated objects because there is no creation and destruction associated with each call.

If you need state information across calls in a farm, make your classes state-aware by implementing methods to read and write the caller's state information. The method call must include a parameter that uniquely identifies the caller. Use this unique identifier to retrieve the associated state before the method performs work and then to write the state afterward. The storage for the state information should be persistent, available to all servers in the farm, and it should support synchronization. A database table is a great option.

The following code demonstrates this pattern in your single-call or singleton-activated classes. This allows you to have state information accessible, but still maintain the ability to place your remote objects in a server farm.

public class YourSingleCallClass
{
  public bool DoSomeWork ( int callIdentifier, int customerNo )
  {
    stateStruct = retrivestateInfo( callIdentifier );
    // Do some operations here on state and parameter(s)
    // potentially update stateStruct
    storeStateInfo( stateStruct );
  }
}

Implementation Considerations

In moving from application design to development, consideration must be given to the implementation details of your remoting code. The performance of cross-application communication can be improved through efficient marshaling and appropriate choice of channel and formatter.

Marshal data efficiently by preferring primitive types. The amount of object data being passed can be reduced by using the NonSerialized attribute. You should also pay particular attention to DataSet serialization and aim to minimize the amount of data serialized from the DataSet. The BinaryFormatter usually produces a more compact representation than the SoapFormatter, although DataSets are still serialized as XML, by default.

By following best practice implementation guidelines, you can increase the performance of your remoting code. The following sections highlight performance considerations for Remoting features and scenarios.

Activation

A remotable type must be created and initialized before it can be accessed. .NET remoting supports server activation and client activation.

Client-Activated Objects (CAOs)

When choosing to use CAOs, consider the following:

  • Use CAOs only where you need to control the lifetime. The lifetime of the CAOs can be controlled by the calling application domain, just as if they are local to the client. Each time a client creates an instance of a client-activated type, that instance services only that particular reference in that particular client until its lease expires and its memory is recycled. If a calling application domain creates two new instances of the remote type, each of the client references invokes only the particular instance in the server application domain from which the reference was returned. For more information, see "Lifetime Considerations."
  • Consider the limited scalability offered by CAOs. CAOs are not generally recommended, due to scalability limitations. Objects activated at the client cause the client proxy reference to be bound to a specific server where the server object was activated. This server affinity reduces the ability of your application to scale, and it negatively impacts performance because load on the individual server increases. When the server load increases, there is no way to offload the calls from the client to another server in the farm that has less load. If you have a single server solution, this is not an issue. However, if you need to scale out and use a server cluster, CAOs significantly limit scalability. CAOs do provide the benefit of allowing the server object to maintain state across method calls. Generally, it is better to design stateless objects for performance and scalability.

**Note   **Any Marshal by Reference Objects (MBROs) returned by the remote object will be treated like CAOs and will suffer this issue as well. Therefore, it is not recommended to return MBRO objects from remoting calls.

Server-Activated Objects (SAOs)

Activation for SAOs is determined by the server. There are two types of SAOs: singleton and single call.

Singleton

Use the following guidelines with singleton SAOs:

  • Use singleton where you need to access a synchronized resource. Singleton is the preferred solution if you need to have a synchronized access to any resource; for example, a read/write operation being performed on a file. Using singletons ensures that there is only a single instance serving the requests from the clients.
  • Use singleton where you need to control lifetime of server objects. Singletons are subject to lifetime leases that are specified for the objects. However, they can be recycled even if clients hold references to the objects after the lease time expires. Therefore, if you need to control the lifetime of server-activated objects, use singletons.
  • Use appropriate state management to scale the solution. The difference between the CAOs and singletons is that of affinity. Singletons can be scaled if they are stateless. Singletons can be used for serving calls from multiple clients, whereas CAOs can be used only for serving calls from the same client for a particular reference. The CLR provides a thread pool to service incoming client calls. As a result, singleton SAOs that maintain shared state require synchronization code to ensure valid state management.

SingleCall

Use the following guideline with single call SAOs:

  • Use SingleCall SAOs for high scalability. Single call objects live only for the life of the method call. They cannot maintain state, because they are destroyed after servicing the method. Single call objects are free from synchronization code, because they serve only requests for a single client before being destroyed. Using single call objects, combined with the HttpChannel and IIS as the host, gives maximum scalability for a .NET remoting solution.

Lifetime Considerations

There are different approaches to determine server object lifetime and specifically when the object should be destroyed. This is because there are many circumstances that can arise that should lead to the server object being released. For example, the client might release its object reference, the network connection might be unexpectedly broken, or the client computer or client process might crash.

With the DCOM protocol, the client computer pings the server every two minutes for each object reference, to indicate to the server that it is still running and connected. If the server fails to receive a ping or a method request within a six-minute interval, the server process automatically releases the object.

.NET Remoting Leases

To reduce network communication, .NET applications no longer use a ping-based approach for distributed garbage collection. Instead, .NET remoting uses a lease-based system to determine the lifetime of a distributed object.

When an object is created, a lease is established that determines the life of the object. The default lifetime for a remote object is five minutes. If the object is not used for a five-minute period, the lease manager releases the object, which makes it available for garbage collection. When an object is called within the five-minute threshold, the following "renewal on call" process occurs:

  • When the call is made, the lifetime of the lease is checked.
  • If the lifetime of the lease is longer than two minutes, nothing is done.
  • If the lifetime remaining on the lease is less than two minutes, the lease is reset to two-minute duration.

**Note   **Both the default lifetime and the renewal on call time can be configured for precise control.

Object Release

When a lease expires, the lease manager in the host process looks at the object whose lease has expired and determines if there is an available sponsor for the object. If a sponsor has been registered, the lease manager calls the sponsor to determine if the object should remain alive and, if so, for how long.

Tune Default Timeouts Based on Need

The general guidelines are as follows:

  • Consider using a longer lease time for objects that are expensive to create. If you use objects that are expensive to create, consider modifying the lease timeouts to allow the object to remain longer than the default 5-minute timeout. For example, if you use a singleton object that incurs an expensive startup process, consider changing the timeout to a longer, more appropriate, period of time, or change the timeout to infinite. The code in the next section shows the changing of the lifetime lease to infinite.
  • Consider shorter lease times for objects that consume lots of shared or important resources. If you create objects that consume shared or important resources, consider using a shorter lease timeout. Setting a timeout of less than 5 minutes will force the cleanup of resources to happen faster, which can help avoid stranded resources and resource pressure.

Tuning the Lease Time

To determine appropriate lifetime timeouts for your application, you need to strike a balance between resource utilization on the server and the performance implications of frequently destroying and recreating objects. Increasing an object's lifetime increases your server's memory and resource utilization, while decreasing the lifetime can lead to objects being destroyed too frequently and prematurely.

**Note   **If a client makes a method call to a remote object whose lifetime lease has expired, an exception is thrown.

You can fine-tune both the lease timeout and the "renew on call" time, either programmatically or declaratively. To alter application-wide initial lease times, use the following code.

public override Object InitializeLifetimeService()
{
    ILease lease = (ILease)base.InitializeLifetimeService();
    if (lease.CurrentState == LeaseState.Initial)
    {
         lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
         lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
          lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
    }
    return lease;
}

A better approach is to use the following configuration file settings.

<configuration>
  <system.runtime.remoting>
    <application>
      <lifetime leaseTime="1M" 
                renewOnCallTime="30S"
                leaseManagerPollTime="2M" />
    </application>
  </system.runtime.remoting>
</configuration>

Note that the preceding approach changes all remote objects published by the server.

Hosts

Choosing the right host can improve the ability to scale out the server infrastructure. There are basically three host types to choose from:

  • IIS and ASP.NET. There are a couple of advantages to using IIS and ASP.NET as the remote host:
    • Security. IIS authenticates client calls. IIS also provides SSL.
    • Scalability. You can create a server farm with multiple servers in a network load balancing (NLB) configuration.
    • Performance. There are two implementations of the CLR and its garbage collection mechanism. One implementation is designed for single-CPU computers. This is Mscorwks.dll, known as Workstation GC. The other implementation is designed to handle multiple-CPU computers. This is Mscorsvr.dll, known as Server GC. ASP.NET uses the Server GC on multiprocessor servers. The Server GC is optimized to maximize throughput and scalability.
  • Windows service. You can create a Windows service to host your remote objects. Doing so does not allow you to load Server GC, so you are limited to the Workstation GC. Services provide a better means of ensuring that your server process is always available, because it can be configured to start when the computer starts in the case of failure. You can also configure Windows services to run under different security contexts.
  • Custom application. You can use either a Windows-based application or a console application to host remote objects. However, in both cases, you have to go to a lot of effort to ensure that the process starts when your computer restarts. Also, configuration of the process to run under a different security context is not as simple as a Windows service. Outside of the development and test environment, this is a less desirable solution.

Choosing whether to host remote components in a custom process, console application, Windows service, or IIS is an important decision. Any host other than IIS is not able to easily provide a secure communication channel. You should consider only a custom process in a trusted server environment. If you do build a custom process, use the TcpChannel for optimum performance.

Recommendations

The following guidelines help you to choose an appropriate host and channel:

  • Use IIS to authenticate calls.
  • Turn off HTTP keep-alives when using IIS.
  • Host in IIS if you need to load balance using NLB.

Use IIS to Authenticate Calls

IIS is the only surrogate that provides secure authentication for .NET remoting solutions. You must use the HttpChannel with the IIS host. You configure your application's authentication type by using the standard IIS Properties dialog box. When you host .NET components in IIS, a virtual directory is created and you should place a Web.config file in the root of the virtual directory. You use this Web.config file to expose the remote server objects. Generally, you should place your remote object assemblies in the \bin subfolder, beneath your application's virtual directory, although you can also place them in the server's global assembly cache.

The following code fragment shows a sample Web.config file. Note that the object Uniform Resource Identifier (URI) that clients bind to must include the ".soap" extension for IIS to know how to route calls to your objects.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <service>
        <wellknown mode="Singleton" type="Namespace.ClassName,AssemblyName" 
                   objectUri="EndpointURI.soap"/>
      </service>
    </application>
  </system.runtime.remoting>
</configuration>

Turn Off HTTP Keep-Alives When Using IIS

The HTTP protocol provides a mechanism to prevent browsers from having to open several connections, just to bring back all the data for a page. HTTP keep-alives enable the browser to open one connection with the server and maintain that connection for the life of the communication. This can greatly increase the browser's performance because it can make multiple requests for several different graphics to render a page.

A .NET remote method call does not require the connection to remain open across requests. Instead, each method call is a self-contained request. By turning off HTTP keep-alives, the server is allowed to free unneeded connections as soon as a method call completes.

To turn off HTTP keep-alives in IIS

  1. Open the Internet Information Services Microsoft Management Console (MMC) snap-in.
  2. Right-click your Web site (not the application's virtual directory), and then click Properties.
  3. Clear the HTTP Keep-Alives Enabled checkbox.

Host in IIS if You Need to Load Balance Using NLB

You cannot load balance across a server farm with the TcpChannel, due to the machine affinity of the underlying Transmission Control Protocol (TCP) connection. This severely limits your application's ability to scale out. To provide an architecture that can scale out, use IIS as the host, combined with the HttpChannel. This configuration provides for the greatest scale out ability, because each method call over the HttpChannel only lives for the life of the method call and maintains no machine affinity.

Use a Custom Host Only in Trusted Server Scenarios

A custom host does not have any built-in mechanism to authenticate calls. Therefore, you should use custom hosts only in trusted server scenarios. The combination of using a custom application with the TcpChannel and Binaryformatter is the fastest approach, in comparison to other remoting or Web service options, although security is the main tradeoff.

With additional development effort, you can develop custom security mechanisms by developing custom sinks, although this is not recommended because it will make porting your solutions to future Microsoft remote communication technologies more difficult.

More Information

For more information about developing custom security solutions for .NET remoting, see ".NET Remoting Authentication and Authorization Sample – Part II" on MSDN at https://msdn.microsoft.com/en-us/library/ms973909.aspx.

For more information about how to secure .NET remoting solutions, see Chapter 13, "Building Secure Remoted Components," in Improving Web Application Security: Threats and Countermeasures on MSDN at https://msdn.microsoft.com/en-us/library/aa302429.aspx.

Channels

.NET remoting uses channels to communicate method calls between two objects in different application domains. Channels rely on formatters to create a wire representation of the data being exchanged. The.NET remoting infrastructure provides the HttpChannel and TcpChannel.

The HttpChannel is used when you use IIS and ASP.NET. While it provides slower performance in comparison to the TcpChannel used with a custom host process, you benefit from the security features provided by IIS:

Consider the following recommendations when choosing a channel type.

  • Use TcpChannel for optimum performance. The TcpChannel in combination with the BinaryFormatter for serializing data provides the best performance remoting solution.
  • Use the TcpChannel in trusted server scenarios. If you choose the TcpChannel for performance reasons, be aware of the security tradeoff. Use this approach only in trusted server scenarios. For more information about how to secure .NET remoting solutions, see Chapter 13, "Building Secure Remoted Components," in Improving Web Application Security: Threats and Countermeasures on MSDN at https://msdn.microsoft.com/en-us/library/aa302429.aspx.

Formatters

A formatter is responsible for taking an object and converting it into a form that can be passed over the communication channel. The .NET Framework supplies two formatters:

  • The SoapFormatter uses XML-encoded SOAP as the message format.
  • The BinaryFormatter uses a native binary representation.

You can use either formatter with both TCP and HTTP channels. Consider the following when choosing a formatter:

  • Use the BinaryFormatter for optimized performance. Use the BinaryFormatter for optimum performance. The BinaryFormatter creates a compact binary wire representation for the data passed across the boundary. This reduces the amount of data that needs to be passed.
  • Consider Web services before using the SoapFormatter. If you need SOAP for interoperability reasons, consider using Web services ahead of the SoapFormatter with .NET remoting. Web services outperform .NET remoting, when using SOAP-based communication.

MarshalByRef vs. MarshalByValue

This section describes the two kinds of remotable objects:

  • Marshal-by-reference (MBR). The state in an MBR object remains where it is and an object reference is passed across the remoting boundary. A proxy is created and used by the client to access the object.
  • Marshal-by-value (MBV). The state in an MBV object is copied and passed across the remoting boundary. A new object with identical state is created at the recipient end.

Marshal-by-Reference

Marshal-by-reference (MBR) objects are accessed by using a proxy object in the source application domain. The .NET remoting infrastructure marshals the calls, sends them to the remote application domain, and invokes the call on the actual object.

MBR can result in chatty calls over the network if the object's interface has not been designed efficiently for remote access. Also, the client proxy may throw exceptions if the network connection breaks.

Marshal-by-reference is appropriate in the following situations:

  • Use MBR when the object state should stay in the host application domain. If the state of the object is relevant only in the host's application domain, use MBR. For example, if the object is referencing a handle to a file or other source such as a database network connection, use MBR.

    You may also want to use MBR when you do not want to serialize and send sensitive data over the network.

  • Use MBR when you need to update data frequently on the server. If the data needs to be frequently updated on the server, using a MBV may serve as a costly option. Use MBR to reduce the cost of serializing the whole of the object. The proxy marshals the data to the server's application domain.

  • Use MBR when the size of the object is prohibitively large. If the size of the object is prohibitively large, it makes sense to use MBR. In this way, the client can access the object's resource directly from the server with only the most relevant data getting passed over the network.

Marshal-by-Value

Marshal-by-value (MBV) objects declare their marshaling rules, either by implementing their own serialization by implementing the ISerializable interface, or by being marked with the Serializable attribute: Consider the following recommendations for using MBV:

  • Use MBV when you need to pass object state to the target application domain. When the state of the object is very lightweight and can easily be passed across application boundaries, use MBV objects. This reduces the lengthy, resource consuming round trips across processes, and application domain boundaries.
  • Use MBV when you do not need to update data on the server. MBV objects are appropriate when the data does not need to be updated on the server and needs only to be passed to the client. This can save server resources, network latency, and network bandwidth.
  • Use small MBV objects when you need to update data frequently on the server. If you frequently need to update data on the server, use small MBV objects where the complete state of the object is passed to the server. Using MBV reduces the marshaling and unmarshaling overhead associated with MBR, especially where non-blittable types are passed.

Serialization and Marshaling

When you use MBV, the object's state must be serialized into a byte stream and be marshaled from source to destination application domain. Serialization and marshaling costs represent a significant proportion of any .NET remoting communication overhead. Use the following recommendations to reduce this impact:

  • Consider using a data facade.
  • Marshal data efficiently and prefer primitive types.
  • Reduce serialized data by using NonSerialized.
  • Prefer the BinaryFormatter.

Consider Using a Data Facade

Consider using a data facade to wrap the most relevant data needed by the client. You can develop a wrapper object, with a coarse-grained interface, to encapsulate and coordinate the functionality of one or more objects that have not been designed for efficient remote access. It provides clients with single interface functionality for multiple business objects.

Alternatively, instead of making a remote call to fetch individual data items, you can fetch a data object by value in a single remote call. When you do that, you operate locally against the locally cached data. This might be sufficient for many scenarios.

In other scenarios, where you need to ultimately update the data on the server, the wrapper object exposes a single method which you call to send the data back to the server.

Marshal Data Efficiently and Prefer Primitive Types

A method call across a remoting boundary is expensive and slow, in comparison to in-process method calls. Make sure that you pass only the data that you need. Avoid passing data that can be simply recalculated.

.NET serialization support makes serializing an object graph very easy by using the Serializable attribute. However, if you overuse this attribute, you ensure that a large amount of extra data is passed when simpler data types would frequently suffice. Try to return value types, such as simple primitive types or structures, first. You should consider using more complex types only if these simple types are not sufficient. A classic example of extreme inefficiency is to return a DataSet that has been populated with a single row, single column value when an integer would do.

Reduce Serialized Data by Using NonSerialized

Serialize only the required data. You can reduce the amount of object state that is serialized by marking specific fields that you do not need to serialize with the NonSerialized attribute as follows.

[Serializable]
Class MyObject: MarshalByRefObject
{
  [NonSerialized]
  Private DataSet dt;
}

**Note   **You need to use the NonSerialized attribute on both public and private fields.

Prefer the BinaryFormatter

The BinaryFormatter produces a compact data representation and should be preferred, unless you have a specific requirement for SOAP, in which case you should use Web services. You can use the BinaryFormatter with both the TcpChannel and HttpChannel.

More Information

For more information about improving the serialization performance, see "How To: Improve Serialization Performance" in the "How To" section of this guide.

DataSets and Remoting

DataSets serialize as XML, even if you use the BinaryFormatter. Passing large DataSets over a remoting channel can consume large amounts of processor and network resources.

To improve DataSet serialization efficiency, start by using column name aliasing to reduce the size of column names, avoid serializing the original and new values for DataSet fields if you do not need to, and serialize only those DataTables in the DataSet that you require.

More Information

For more information about how to improve the performance of dataset serialization, see "How To: Improve Serialization Performance" in the "How To" section of this guide.

To implement binary serialization, see Knowledge Base article 829740, "Improving DataSet Serialization and Remoting Performance" at https://support.microsoft.com/default.aspx?scid=kb;en-us;829740.

For more information about serializing ADO.NET objects, see "Binary Serialization of ADO.NET Objects" on MSDN at https://msdn.microsoft.com/en-us/magazine/cc188907.aspx.

Summary

This chapter has covered the main architectural and design considerations for .NET remoting. Considerations, such as choosing an appropriate host, channel, and formatter, can impact both the performance and potential scalability of your .NET remoting solutions.

This chapter has also shown specific coding techniques, such as how to improve serialization performance, how to control object lifetime, and how to synchronize multithreaded servers.

Additional Resources

For more information, see the following resources:

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

© Microsoft Corporation. All rights reserved.