Monthly Archives: April 2007

WCF Sessions and Reliable Messaging

There are a couple of ways to establish a session between client and service. The session is established by identifying clients via a unique identifier. The unique identifier is either conveyed by

  • the client credentials when WS-Security is utilized to established secure session
  • the TCP/IP socket connection when using an underlying connection-oriented protocol such as TCP
  • the WS-ReliableMessaging protocol token when requiring message ordering and message delivery assurance for transport protocols.

Read more about how WS-Reliable Messaging protocol in my article “How does Reliable Messaging work?

Enabling sessions are all done in the configuration file. Some bindings are sessionful by default like the tcpBinding and wsHttpBinding.

I continue with Hello World WCF code sample from my earlier articles: “Building a Windows Communication Foundation client” and “A simple Windows Communication Foundation Web Service”. You can download the source code from here: Hello World WCF with clients.

Just by changing the binding in the code sample configuration to wsHttpBinding in the service and the clients, you get secure sessions; wsHttpBinding is by default secured with message security. The secure session context is established with the WS-SecureConversation protocol.

In the service type implementation it is possible to retrieve the session identifier via the OperationContext.Current.SessionId.

If you want un-secure reliable ordered messages with sessions, then change the behavior of the wsHttpBinding by configuring the binding like below. The configuration shown is for the service, but the changes (in bold) are exactly the same as required in the clients’ configuration files.

< ?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system .serviceModel>
    <behaviors>
      <servicebehaviors>
        <behavior name="myBehavior">
          <servicemetadata httpGetEnabled="true"
                           httpGetUrl="http://localhost:8080/HelloWorldService" />
        </behavior>
      </servicebehaviors>
    </behaviors>
    <bindings>
      <wshttpbinding>
        <binding name="reliableBinding">
          <reliablesession enabled="true" ordered="true"/>
          <security mode="None" />
        </binding>
      </wshttpbinding>
    </bindings>
    <services>
      <service name="HelloWorldService"
               behaviorConfiguration="myBehavior">
        <endpoint address="http://localhost:8080/HelloWorldService"
                  binding="wsHttpBinding"
                  bindingConfiguration="reliableBinding"
                  contract="IHelloWorldService" />
      </service>
    </services>
  </system>
</configuration>

Now the session identifiers are conveyed by the WS-Reliable Messaging protocol (linie 13-18). It is possible to use secure and reliable messages, but security is disabled to prove the point of WS-Reliable Messaging can be used to establish sessions.

If the implementation of your service requires sessions, decorate the service contract with the SessionMode.Required – this will demand that every endpoint bindings exposing the service support sessions. The possible values of the SessionMode enum are Required, Allowed and NotAllowed where Allowed is default.

[ServiceContract(SessionMode=SessionMode.Required)]
public interface IHelloWorldService
{
    [OperationContract]
    string HelloWorld();
}

If guaranteed ordering of messages is assumed by the implementation and therefore required for dependable behavior of the service, then decorate the service contract with the DeliveryRequirements attribute with the parameter RequireOrderedDelivery set to true.

[ServiceContract(SessionMode=SessionMode.Required)]
[DeliveryRequirements(RequireOrderedDelivery=true)]
public interface IHelloWorldService
{
    [OperationContract]
    string HelloWorld();
}

If the configuration of an endpoint does not fulfill the requirements, the host throws an exception detailing the missing requirements.

When to use the sessions
Sessions in WCF does not deliver the same functionality as in ASP.Net or ASMX based Web Services. For instance the HttpSessionState store is not available, not even if the WCF service is hosted in the IIS. WCF sessions are similar to Remoting sessions and are only for service instancing.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class HelloWorldService : IHelloWorldService
{
    public string HelloWorld()
    {
        Console.WriteLine("Invoked by client with session ID {0}",
            OperationContext.Current.SessionId);

        return "Hello World";
    }
}

To control the instancing of the service type objects, decorate the service type with the ServiceBehavior attribute and specify the InstanceContextMode enum as in the above code.

The InstanceContextMode values are:

  • PerCall – A new InstanceContext object is created prior to and recycled subsequent to each call. If the channel does not create a session this value behaves as if it were PerCall.
  • PerSession – A new InstanceContext object is created for each session.
  • Single – Only one instance of the service type object is used for all incoming calls and is not recycled subsequent to the calls. If a service type object does not exist, one is created.

Download the sample code with reliable messaging here (Hello World WCF Reliable Messaging) and read more about WCF sessions here.

Strings in .Net

Strings in .Net are immutable reference types, but can be confusing because they sometimes have similar characteristics as value types.

Below is a code sample that shows the value type characteristics of string.

string s1 = "Anders";
string s2 = "Anders";

Console.WriteLine("s1 and s2 are equal : {0}", s1 == s2);

Output:
s1 and s2 are equal : True

For regular reference types this would have been an object reference compare, but the == operator is overloaded to execute the same logic as the String.Equals method.

Continuing the example by implicit cast each string to an object:

object o1 = s1;
object o2 = s2;

Console.WriteLine("o1 and o2 are equal : {0}", o1 == o2);

Output:
o1 and o2 are equal : True

These two strings are equal due to the CLR optimization called interning. Interning works by having an internal pool of unique literal strings. If the same literal string is assigned to multiple variables the runtime retrieves the reference to the literal string in the internal pool and assigns it to each variable.

Console.WriteLine("s1 and s2 are same : {0}", object.ReferenceEquals(s1, s2));
Console.WriteLine("o1 and o2 are same : {0}", object.ReferenceEquals(o1, o2));

Output:
s1 and s2 are same : True
o1 and o2 are same : True

The Object.ReferenceEquals determines whether the specified object instances are the same instance.

When comparing the strings or objects all of them are the same instance! This is again due to interning. All of the variables reference to the same object.

Let us rewrite the code and try something a little bit different:

string s1 = "Anders";
string s2 = new StringBuilder("Anders").ToString();

object o1 = s1;
object o2 = s2;

Console.WriteLine("s1 and s2 are equal : {0}", s1 == s2);
Console.WriteLine("o1 and o2 are equal : {0}", o1 == o2);
Console.WriteLine("s1 and s2 are same : {0}", object.ReferenceEquals(s1, s2));
Console.WriteLine("o1 and o2 are same : {0}", object.ReferenceEquals(o1, o2));

Output:
s1 and s2 are equal : True
o1 and o2 are equal : False
s1 and s2 are same : False
o1 and o2 are same : False

The above code is almost identical to the previous code except that s2 is initialized with a StringBuilder. Will this return the same result? No, because interning only occur when an assembly gets loaded or the String.Intern method is called.

The first string compare is true because of the operator overloading discussed earlier, but all the other compares are false. Even the o1 and o2 compare, because the runtime is unaware of the object types at the time of the comparison and can therefore not use the overload operator.

If you want to know more about strings, interning or internationalization issues with strings – read on.

Garbage Collection Flavors

Why should you care about Garbage Collection? Well, it may very well improve performance for your applications.

The .Net framework garbage collector can operate in different modes depending on platform and requirements. There are three modes available for .Net framework version 2.0 and 3.0. Each of these modes is tailored for specific situations.

Concurrent Workstation Garbage Collection

This mode is optimized for interactivity by frequent short garbage collects. Each collect is split up into smaller pieces and are interleaved with the managed applications threads. This improves responsiveness at the cost of CPU cycles. This is ideal for interactive desktop applications where freezing application is an annoyance for the users and ideal CPU time is abundant when waiting for user input. Concurrent workstation mode improves the usability with perceived performance.

Note that interactive GC only applies for Gen2 (full heap) collects because Gen0 and Gen1 collects are in nature very fast.

Non-concurrent Workstation Garbage Collection

Non-concurrent workstation mode works by suspending managed application threads when a GC is initiated. It provides better throughput but might appear as application hiccups where everything freezes for the users.

Server Garbage Collection

In server mode a managed heap and a dedicated garbage collector thread is created for each CPU. This means the each CPU allocates memory in its own heap therefore results in lock-free allocation. When a collect is initiated all the managed application threads are suspended and all the GC threads collect in parallel.
Another thing to note is that the size of the managed heap segments is larger in server mode than workstation mode. A segment is the unit of which the memory is allocated on the managed heap.

It is possible to choose the type of GC for a managed application in the configuration file. Under the <Runtime> element add one of the below three settings and depending on the number of CPU, the garbage collector will run in the configured mode.Garbage Collection type settings

Running a standalone managed application the GC mode is by default concurrent workstation. Managed application hosts like ASP.Net and SQLCLR run with Server GC by default.

If you want to know more about how the GC works, read the blog entries “Using GC Efficiently”
by Maoni.