Yearly Archives: 2010

Microsoft Julekalender låge #7 vinder

Yet another blog post in Danish, sorry.

Vinderen af gårsdagens Microsoft Julekalender låge #7 fundet. Vinderen er Gianluca Bosco, som har indsendt følgende WCF klient til servicen:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Ready? Press [ENTER]...");
        Console.ReadLine();

        var factory = new ChannelFactory<Shared.IMyService>(
            new WSHttpBinding(),
            new EndpointAddress("http://localhost:8080/MyService"));

        factory.Endpoint.Binding.SendTimeout = new TimeSpan(0,2,0);

        var names = new[] { "Anders", "Bende", "Bo", "Egon",
            "Jakob", "Jesper", "Jonas", "Martin", "Ove",
            "Rasmus", "Thomas E", "Thomas" };

        var x = from name in names.AsParallel()
                    .WithDegreeOfParallelism(12)
                select Do(factory, name);

        x.ForAll(Console.WriteLine);

        Console.WriteLine("Done processing...");
        Console.ReadLine();
    }

    static string Do(ChannelFactory<Shared.IMyService> factory,
         string name)
    {
        var proxy = factory.CreateChannel();

        var result = proxy.LooongRunningMethod(name);

        return result;
    }
}

Gianluca har rigtig nok fundet den værste performance synder af dem alle, at man ikke skal instantier en ChannelFactory for hvert kald. Alene denne forbedring kan halvere tiden brugt ved et WCF kald.

Desuden fandt Gianluca den indbyggede fælde i min implementation. Server implementationen kalder Thread.Sleep (mellem 1 og 100 sekunder) for at simulere langvarigt arbejde. Default SendTimout på wsHttpBinding (og alle andre bindings) er 1 minut, hvilket betyder, at klienten vil få en TimeoutException pga. serverens lange arbejde.

Tillykke til Gianluca med hans nye helikopter.

Der er en mindre optimering, som kan forbedre performance yderligere og det er at kalde Open og Close på en Channel explicit. Det skyldes, at der i en implicit Open er thread synchronisation, således at kun én thread åbner en Channel og de resterende threads venter på at Channel er klar.

Hvis du har forslag til yderligere forbedringer, så skriv en kommentar.

Microsoft Julekalender låge #7

Sorry – this post is in Danish.

Dagens opgave handler om Windows Communication Foundation. WCF er kompleks pga. mængden af funktionalitet og kan derfor virke indviklet. Kompleksiteten afspejles også i størrelsen på WCF assembly System.ServiceModel.dll, som er klart den største assembly i hele .Net Framework Class Library (FCL) … selv større end mscorlib.dll.

Opgaven:

Implementer en klient til nedstående service, som benytter WSHttpBinding med default settings.

[ServiceContract(Namespace = "www.lybecker.com/blog/wcfriddle")]
public interface IMyService
{
    [OperationContract(ProtectionLevel =
        ProtectionLevel.EncryptAndSign)]
    string LooongRunningMethod(string name);
}

public class MyService : IMyService
{
    public string LooongRunningMethod(string name)
    {
        Console.WriteLine("{0} entered.", name);

        // Simulate work by random sleeping
        var rnd = new Random(
            name.Select(Convert.ToInt32).Sum() +
            Environment.TickCount);
        var sleepSeconds = rnd.Next(0, 100);
        System.Threading.Thread.Sleep(sleepSeconds * 1000);

        var message = string.Format(
            "{0} slept for {1} seconds in session {2}.",
            name,
            sleepSeconds,
            OperationContext.Current.SessionId);
        Console.WriteLine(message);

        return message;
    }
}

Klienten må meget gerne være smukt struktureret og skal:

  • Implementeres i .Net 3.x eller .Net 4.0
  • Simulere et dusin forskellige klienter
  • Være så effektiv som mulig (tænk memory, CPU cycles, GC)

Beskriv kort jeres valg af optimeringer.

For at gøre opgaven nemmere at løse, så har jeg allerede løst den for jer… dog ikke optimalt. Download min implementation.

Send løsning til anders at lybecker.com inden midnat; vinderen vil bliver offentligt i morgen og vil blive den lykkelige ejer af en fjernstyrret helikopter med tilbehør, så den er klar til af flyve. En cool office gadget. Helikopteren er nem at flyve og kan holde til en del. Det ved jeg af erfaring 🙂

Se helikopteren flyve nedefor.

ANUG Solr/Lucene presentation

Aarhus .NET user groupI am on the train to Copenhagen after a successful presentation of Solr/Lucene at the Aarhus .NET user group.

The presentation went very well judging by the number of questions during the almost 2½ hour long presentation and the feedback afterwards. Love it – thanks 🙂

The presentation and code samples can be downloaded below:

Please do contact me if you have any further questions – I’ll love to help out.

WCF Timeouts

The last two articles about WCF Throttling part 1 and part 2 would not be complete without looking at WCF timeouts. Any potentially lengthy operation must have a timeout or the system might end up waiting indefinitely – this is remarkably prevalent when working across any network connection (Yes, LAN connections too).

Timeouts are not directly related to throttling properties, but effect the way the service (or client) performance under load. Timeout properties can be perceived as an annoyance when sending larger messages or dealing with slow connections or services. The frustration increase as the naming of the properties can be deceiving. Read on… and I’ll explain 🙂

Below are the binding properties that all throw TimeoutExceptions if any of setting thresholds are exceeded:

  • OpenTimeout (TimeSpan) – the interval of time provided for an open operation to complete including security handshakes (WS-Trust, WS-Secure Conversation etc.). The default is 00:01:00.
  • CloseTimeout (TimeSpan) – the interval of time provided for a close operation to complete. The default is 00:01:00.
  • SendTimeout (TimeSpan) – the interval of time provided for an entire operation to complete. This includes both sending of message and receiving reply! The default is 00:01:00.
  • ReceiveTimeout (TimeSpan) – the interval of time that a connection can remain inactive, during which no application messages are received, before it is dropped. The default is 00:10:00.
    • This setting is only used on the server-side and has no effect on client-side.
    • When using Reliable Sessions remember to set the InactivityTimeout property on the reliableSession element to the same value as the ReceiveTimeout property, as both inactivity timers has to be satisfied.

Example of configuration file:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="netTcpBindingConfig"
               openTimeout="00:01:00"
               closeTimeout="00:01:00"
               sendTimeout="00:01:00"
               receiveTimeout="00:10:00">
        <reliableSession enabled="true"
                         inactivityTimeout="00:10:00" />
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>

WCF Throttling – Part 2

In the WCF Throttling – Part 1 article the service throttling behavior was introduced.

There are other throttling features in WCF that are designed to protect the service from request flooding.

These WCF throttling feature are configured on the binding, service behaviors and endpoint behaviors.

Binding properties:

  • MaxConnections (int) – specifies the maximum number of outbound and inbound connections the service creates and accepts respectively. Default value is 10 connections. This setting only applies for statefull TCP connections like netTcpBinding and not stateless HTTP protocols like basicHttpBinding, wsHttpBinding or webHttpBinding.
  • MaxReceivedMessageSize (long) – the maximum size of a message (including headers), that can be received on a channel. The sender of a message exceeding this limit will receive a fault and the receiver will drop the message. The default value is 65,536 bytes (64K).

There are two additional properties on the binding that one might mistakenly think is request throttling properties. These are the MaxBufferPoolSize and MaxBufferSize properties and they control WCF memory Buffer Manager.

Note: remember to set the MaxReceivedMessageSize and MaxBufferSize properties to the same value if using TransferMode.Buffered or an ArgumentException will be thrown at runtime with the message “For TransferMode.Buffered, MaxReceivedMessageSize and MaxBufferSize must be the same value.”

Binding properties for the readerQuotas element – used by XmlReader under the hood:

  • MaxArrayLength (int) – the maximum allowed array length of data received from a client. The default is 16,384 (16K).
  • MaxBytesPerRead (int) – the maximum allowed bytes returned per read for the XmlReader. The default is 4,096 (4K).
  • MaxDepth (int) – the maximum XML nested node depth. The default is 32.
  • MaxNameTableCharCount (int) – the maximum characters allowed in a table name. This is the maximum length of an XML element or attributes identifier including XML namespace. The default is 16,384 (16K).
  • MaxStringContentLength (int) – the maximum characters allowed in XML element or attribute content. The default is 8,192 (8K).

The DataContractSerializer is by default used to serialize and deserialize messages as it is much faster the XMLSerializer, but with less features. The DataContractSerializer has a single property that can be configures at the endpoint or service behavior:

  • MaxItemsInObjectGraph (int) – maximum number of items in an object graph to serialize or deserialize. The default is 65,536 (64K).

Resist the temptation of settings any of these properties to Int.MaxValue and the likes, because determining the correct values are difficult. Throttle the service, so some clients gets served instead of risk boggling down the service with request flooding, resulting in no clients get served.

You will become the service hero in your organization by throttling instead of letting the service run wild 🙂

Example of configuration file:

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="endpointBehavior">
        <dataContractSerializer maxItemsInObjectGraph="65536"/>
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      <behavior name="serviceBehaviors">
        <dataContractSerializer maxItemsInObjectGraph="65536"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <netTcpBinding>
      <binding name="netTcpBindingConfig"
                maxReceivedMessageSize="65536"
                maxConnections="10">
        <readerQuotas maxArrayLength="16384"
                      maxBytesPerRead="4096"
                      maxDepth="32"
                      maxStringContentLength="8192"
                      maxNameTableCharCount="16384"/>
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>