Click here to Skip to main content
Click here to Skip to main content

Remoting Compression Channel Sink

, 12 Nov 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
An article explaining a Remoting extensible channel sink architecture and an implementation of the compression channel sink.

Introduction

One of the problems with Remoting in real world is that sometimes it is required to transfer a large chunk of data between a client and a server. There is a big overhead with the default binary serializer, which is very chatty. The result is, Remoting errors associated with large requests and poor performance. There is a global solution, which allows compressing the Remoting requests and responses, thus alleviating the problem of exceeding the Remoting maximum request size. This is an in-depth look at a Remoting extendable architecture, which provides detailed information of the implementation of compression.

Remoting

A possible design approach related to compression can be built around a Remoting extendable architecture and the customization of the channel. Channels send each message along a chain of channel sink objects prior to sending, or after receiving, a message. By default, a sink chain contains sinks required for the basic functionality of the channel, such as proxy, formatter, and transport. The channel sink chain processes a message that is sent to or from an application domain, and this process can be augmented by inserting a custom processing sink, in our case, a custom compression sink, and subsequent processing will use the message that is returned to the system after processing. The following illustration shows the structure of a channel sink chain:

Both the server and the client channels can be configured to use compression programmatically, or by using a configuration file. The client side compression sink is implemented using two classes where one is a provider, CompressionClientChannelSinkProvider, and the other a sink, CompressionClientChannelSink. For the server side, the sink is implemented using two classes, where one is a provider, CompressionServerChannelSinkProvider, and the other a sink, CompressionServerChannelSink. Next, we will review a sample code with the custom compression sink, which represents a typical application designed using layered architecture, where the services layer is responsible for communication with other layers using a request/response design pattern.

Sample

We have created a sample application which utilizes the compression channel sinks. Defined below is a sample request object derived from a generic ServiceBase<t> class:

[Serializable]
public class ConcreteTypeRequest : ServiceBase<concretetype>
{
    private int _userId;
    public int UserId
    {        
        get { return _userId; }
        set { _userId = value; }
    }
    public ConcreteTypeRequest()
    {}
}

Next, a server configuration file and a client configuration file should contain the settings for the custom compressing sink on the server and the client side, respectively. Below is an example of the config file for stackable providers using the Remoting extendable framework. The most important thing is the order in which a provider and a default formatter is specified within the serverProvider section. Also, it provides a compression threshold parameter, which allows specifying the threshold in bytes:

Server configuration:

<configuration> 
  <system.runtime.Remoting>
    <application>
      <service>
         <wellknown type="Business.BusinessManager,
              Business"objectUri="BusinessManager.rem"mode="SingleCall"/>
      </service>
      <channels>
        <channel ref="tcp" port="5000">
          <serverProviders>
            <provider type="Util.CompressionServerChannelSinkProvider,     
               Util"compressionThreshold="500000"/>
            <formatter ref="binary" />
          </serverProviders>
        </channel>
      </channels>
    </application>
   </system.runtime.Remoting>
</configuration>

Client configuration:

<configuration>
   <system.runtime.Remoting>
     <application>
       <client>
         <wellknown type="Business.BusinessManager, Business" 
            objectUri="BusinessManager.rem" 
            url ="tcp://localhost:5000/BusinessManager.rem"/>
       </client>
       <channels>
         <channel ref="tcp">
           <clientProviders>
             <formatter ref="binary" />
             <provider type="Util.CompressionClientChannelSinkProvider,          
                 Util"compressionThreshold="500000"/>
           </clientProviders>
         </channel>
       </channels>
     </application>
   </system.runtime.Remoting>
</configuration>

By default, the compression is enabled for all requests and responses within an AppDomain. If a request size in bytes is under the threshold, the request is transferred without being compressed. If it is greater than the threshold which, in our case, is equal to 500000 bytes, it is compressed before being transferred to the server. If we want to opt out, the NonCompressible attribute should be specified on the class, as follows:

[Serializable]
[NonCompressible]
public class ConcreteTypeRequest : ServiceBase<concretetype>
{
    private int _userId;
    public int UserId
    {        
        get { return _userId; }
        set { _userId = value; }
    }
    public ConcreteTypeRequest()
    {}
}

Moreover, the NonCompressible attribute is unconditional, thus permanently disabling the compression for this type of request. This might be useful for some scenarios in the enterprise, when, for example, a request's payload is already compressed. If you want the compression to be conditionally applied to certain instances, a request may implement an ICompressible interface as follows:

[Serializable]
public class ConcreteTypeRequest : ServiceBase<concretetype>, ICompressible
{
    private int _userId;
    public int UserId
    {
        get { return _userId; }
        set { _userId = value; }
    }
 
    public ConcreteTypeRequest()
    {}
 
    #region ICompressible Members
 
    public bool PerformCompression()
    {
        return false;
    }
 
    #endregion
}

The PerformCompression method returns a boolean value, which determines if the request is compressible based on the payload's state within a request.

And finally, attached is a sample application which implements the compression channel sink, a server, and a client application. It is developed for Microsoft Visual Studio 2005, and contains a console application for testing purposes.

Conclusion

To sum up, we looked at the extensibility of the Remoting architecture by implementing a custom compression sink, which solves the problem of performance encountered when large requests and responses are sent over the wire. We implemented the configurable sink when a request or response can be opted out from the compression unconditionally, or based on the conditions determined at runtime. We reviewed the settings for the configuration files which are required to plug into the Remoting infrastructure, and how to configure a threshold for compression. Finally, we looked at a sample application which demonstrates a working prototype of the compressing sink.

History

  • November, 12, 2008 - Initial revision.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

aschmidt

United States United States
Alexander Schmidt. I'm a software developer, who is working primarily with Microsoft technologies including Microsoft .NET. I'm also interested in optimization problems and software engineering in general. You can visit my blog at http://www.alexschmidt.net

Comments and Discussions

 
GeneralSolution for Sink Problem. Pinmemberteligaurav3-Mar-10 20:17 
GeneralCompression Sink Problem Pinmemberteligaurav3-Mar-10 0:26 
GeneralCompression Sink suddenly stopes working [modified] Pinmemberteligaurav19-Jan-10 20:36 
GeneralI don't see diference using this compression and without it! PinmemberAlexsandro_xpt9-Aug-09 9:40 
GeneralRe: I don't see diference using this compression and without it! Pinmemberaschmidt4-Nov-09 12:59 
GeneralRe: I don't see diference using this compression and without it! PinmemberAlexsandro_xpt4-Nov-09 15:22 
GeneralRe: I don't see diference using this compression and without it! Pinmemberaschmidt16-Nov-09 6:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411028.1 | Last Updated 13 Nov 2008
Article Copyright 2008 by aschmidt
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid