Sajay

Life, The Universe and Everything Distributed.

August, 2009

Posts
  • Sajay

    HTTP polling duplex - Performance

    • 0 Comments
    Note: Cross posted from Sajay.
    Permalink

    Really good article on Performance of HTTP polling duplex server-side channel in Microsoft Silverlight 3 by Tomek from the ServiceModel/SL team.

    http://tomasz.janczuk.org/2009/08/performance-of-http-polling-duplex.html

  • Sajay

    Applying behaviors on the client channel

    • 0 Comments
    Note: Cross posted from Sajay.
    Permalink

    When we need to modify or see the message before its sent or after its received, we generally can use a Message inspector. However sometimes we want to be a bit more granular. One such requirement was to perform some operations for 2-way calls and a different set of operations for one way calls. For this you can probably use extensibility points like the IParameterInspector and attach the required inspector to those appropriate operations.

     

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        foreach (ClientOperation operation in clientRuntime.Operations)
        {
            if (!operation.IsOneWay)
            {
                operation.ParameterInspectors.Add(new TwoWayBehavior());
            }
            else
            {
                operation.ParameterInspectors.Add(new OneWayBehavior());
            }
        }
    }

    Here is the source.(3.13 kb)

  • Sajay

    WCF 4: AddDefaultEndpoints

    • 0 Comments
    Note: Cross posted from Sajay.
    Permalink

    Here is another little goodie we have which will help in reducing configuration. You can use the ServiceHostBase.AddDefaultEndpoints which will pretty much probe your service implementation for contracts and expose them as shown below. Notice that I don't need to specify anything more than the base address and the type of the service and I have actually commented out the call to the API. You can find more details about the simplified configuration here.

    const string address = "net.tcp://localhost:8080/";
    const string address2 = "http://localhost:8081/";
    ServiceHost host = new ServiceHost(typeof(Service1), new Uri(address), new Uri(address2));
    //host.AddDefaultEndpoints(); 
    host.Open();
    

     

    AddDefaultEndpoints

  • Sajay

    How do I get the workflow InstanceId?

    • 0 Comments

    Note: Cross posted from Sajay.
    Permalink

    You can use a CodeActivity that returns a single result.

     

        public sealed class GetWorkflowInstanceId : CodeActivity<Guid>
        {
            protected override Guid Execute(CodeActivityContext context)
            {
                return context.WorkflowInstanceId;
            }
        }
  • Sajay

    Hello World Workflow Service 4.0

    • 0 Comments
    Note: Cross posted from Sajay.
    Permalink

    Building a workflow service using 4.0 gives a very neat set of capabilities from both WF and WCF. Similar to WCF we can fully define a workflow either in code or otherwise just using Xaml. Here I chose a fully code based approach. If you just want the source you can download it here.

    The Service Contract

    We generally can take a workflow first approach or a contract first. To keep things simple, I have a very bare service contract as shown below.

     

    [ServiceContract]
    interface IService1
    {
        [OperationContract]
       
    void GetData();
    }

    I also hold on to the contract description. This is just convenience and to avoid some constants like service name etc.

    ContractDescription description = ContractDescription.GetContract(typeof(IService1));

    The Operation

    The idea here is to build the service bottom up from operation we need to perform. I can think of my workflow as composition of activities. The functionality of my service is quite simple here. All I do is write a message to the console. So the body of my operation will look something like this.

    new WriteLine

       
    TextWriter = Console.Out,
       
    Text ="Hello Workflow."
    },

    The Implementation

    Now I need to make this an operation. An operation has an associated message exchange pattern, commonly referred to as MEP. In my case it's a simple receive reply pattern. This means I have to compose my work in between a Receive and a SendReply. I am also going to tie this all up in Sequence as shown below.

    Sequence sequence = new Sequence
    {
       
    Activities =
       
    {
           
    receive,
           
    new WriteLine 
           
    {
               
    TextWriter = Console.Out, Text ="Hello Workflow."
           
    },
           
    reply
       
    }
    };

    The Message Exchange

    The next thing is to lay out my Receive and Reply which will define the wire format of the messages.

    1. The receive needs to know the operation that the client can invoke. Also I need to make sure that the workflow can be instantiated by this particular operation. For this I need to set the CanCreateInstance property. Also the serializer used by default is the DataContractSerializer.

    Receive receive = new Receive
    {
        OperationName = description.Operations[0].Name, 
        CanCreateInstance = true
    };

    • The Reply is send back to the client using my SendReply activity. This reply is a part of a conversation and it needs to know which request it would respond to. I can do this by pointing the SendReply to the instance of the corresponding Receive. Also I don't have any data here so it is an empty parameter list. (the operation is not Messages contract based in my case but this is generally a better option for more control and performance.)

    SendReply reply = new SendReply

        Request = receive, 
       
    Content = new SendParametersContent { }
    };

    • I now need to define the workflow service which would hold this Sequence and also need to specify the full name of the service definition. For this I can use the description object to get the name, namespace etc.

    WorkflowService serviceDefinition = new WorkflowService
    {
        Body = sequence,
        Name = XName.Get(description.Name, description.Namespace)
    };

    The Host

    The next step is to give this definition to the workflow service host so that it can start the service. Here I self host the workflow as shown below.

    WorkflowServiceHost host = new WorkflowServiceHost(serviceDefinition, 
                                                       new Uri("http://localhost:8080"));
    host.AddServiceEndpoint(serviceDefinition.Name, new BasicHttpBinding(), "");
    host.Open();

    The Test

    Finally I can test the workflow using a simple proxy.

    ChannelFactory<IService1> cf = new ChannelFactory<IService1>(new BasicHttpBinding(),
                                                                  "http://localhost:8080"
    );
    IService1 proxy = cf.CreateChannel();
    proxy.GetData();
    ((IChannel)proxy).Close();

  • Sajay

    Channel9: Monitoring WF Services

    • 0 Comments
    Note: Cross posted from Sajay.
    Permalink

      10-4 Episode 24: Monitoring Workflow Services

    by Ron Jacobs -

    One of the great advantages to building services with WCF and Windows Workflow 4 is that the environment is instrumented with loads of events that allow you to track what exactly is happening.  This is useful for health monitoring, troubleshooting and other scenarios like auditing and compliance.  In this episode I'll take you through the monitoring lab from the Visual Studio 2010 training kit and show you how you can take advantage of these powerful capabilities.

    Get Microsoft Silverlight
  • Sajay

    Concurrent Receives - MaxPendingReceives

    • 0 Comments

    Note: Cross posted from Sajay.
    Permalink

    One of the performance improvements we did with WCF 4.0 was to enable concurrent receives. This greatly helps scenarios where we need to do some kind of work like DB authentication with username passwords or custom channels that may need to log something. Primarily if any path during message receive requires some concurrency, then this is the knob you need to consider.

    Here are some common questions and answers regarding concurrent receives and should also help you decide if you need this and if you do what value would benefit you.

    <endpointBehaviors>
          <behavior name
    ="MyEndpointBehavior">
                      <dispatcherSynchronization maxPendingReceives
    ="5" />
          </behavior
    >
    </endpointBehaviors>

    Why do we need this?

    • I have a custom username password that seems to be taking a long time and requests are processed sequentially.
    • I have a custom channel that is taking a long time and messages are not processed concurrently.
    • Other extensibility points that causes my channel to block.

    Rule of thumbDo not do blocking work in your channels!!!!

    Q: Then where can I do the work?
    A: There are 2 areas where work can be done between your application and the transport. You need to understand the receive loop mentioned here. Try to push your work to the dispatcher side as much as possible. These include extensibility points like Message Inspector and try avoiding blocking work in the channel layer. The overhead here is that you need to copy over the message since you cannot modify the message object and hence memory should be the resource you need to think about. 

     

    Q: What happens when we do some blocking work in the channel layer?
    A: You end up blocking your receive loop! This means that the next message will not be received until you complete your receive loop. The channel’s receive loop is single threaded in nature by default since its only duty is to take a message on the transport and hand it over to the dispatcher. It is a low level message pump which does nothing but give work to the dispatcher so any additional overhead actually means you slow down the main message loop. This will stop other messages from being picked up and dispatched. You generally see client timeouts. You can consider this like the windows message pump which will freeze up your UI.

     

    Q: I don’t have an option and need to do this work in the channel, what can I do?
    A: Generally if you needed to do some work at the channel layer and this had to be blocking there was no way other than take care of this issue directly in the channel. This is because the ideal channel doesn’t block. Till netfx 3.5 there was no option besides moving the work up or even doing some really wacky custom channel to do this work on another thread and continue the loop. If you really need a sample ping me. But in 4.0 we kind of understood that there might be cases where you really have no option and are ready to take this performance penalty. For that reason we introduced a knob called MaxPendingReceives that you can use for this.

     

    Q: What does MaxPendingReceives do?
    A: This knob issues multiple receives to the underlying channel. You can configure a DispatcherSynchronizationBehavior and specify the MaxPendingReceives value indicating how many concurrent receives can be issued on the channel.

     

    Q: What is the overhead for this?
    A: The implementation is a simple queue and the overhead generally is less than a percent for small values. The larger the queue size, the more number of concurrent receives there will be and you see that your throughput doesn’t improve since you see more context switches and contention rather than optimized concurrency.

     

    Q: Why/How do I configure MaxPendingReceives?
    A: This value should be considered only after you have properly configured service throttling behavior. These are generally your first level throttles. If you don’t understand the points mentioned in the earlier section regarding the receive loop or you don’t have any of the extensibilities, then you probably don’t need this behavior and need to get take a harder look at your service performance before you even consider turning ON this knob.

    Consider an 8 core system here and assume you have some CPU intensive operation like computing hash, that you need to do in the channel. This means you can probably have about 8 messages simultaneously being processed and nothing more since you would just cause the message to be accepted and wait till the CPU is available (remember your service operation also needs CPU time). So if the work is more CPU bound try to limit it to the number of cores.

    On the other hand if you have some blocking work that would go ahead and access some disk and you can churn out more messages then you need to tweak this value to a sweet spot and there is no magic number. Generally we have seen that staying close to the number of cores or a factor of 2 has been optimal. Bottom line is – CHECK YOUR CPU UTILIZATION. If its already maxed out then this will only reduce your throughput.

    <endpointBehaviors>
          <behavior name=“MyEndpointBehavior”>
                <dispatcherSynchronization maxPendingReceives=”4“ />
          </behavior>
    </endpointBehaviors>

    Q: Are there any issues to turning on MaxPendingReceives?
    A: There are 2 side effects to this. One is the that your channel will issue multiple BeginTryReceives before an End is completed and second is the overhead mentioned. The point you need to keep in mind is that since you are enabling concurrent receives on your channel, your channel also needs to be concurrency aware. The behavior change here is that the channel stack’s BeginTryReceive will be invoked N number of times to enable multiple receives and this fills up the receive queue initially. This is a behavior change in how channels were used till now since the EndTryReceive doesn’t happen immediately after the first BeginTryReceive and also the completions might not happen in the same order.  If you require completion ordering, your service should also guarantee ordering. This would be a topic by itself and so the point here is that if the service behavior allows concurrent processing the channel would allow messages also to come in a FIFO completion order.

Page 1 of 1 (7 items)