AppFabric Applications: Episode III–Stateful Services

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

On of Services provided by AppFabric Application foundation is so called StateFul Service. This is is in fact WCF service with the ability persists and to replicate its state. For years we have been developing WCF based service. Did you ever ask yourself how to build the WCF service able to scale (in cluster)? In many scenarios this is even not a series issue, because statistically most services works by pattern Request Reply without persisting of state. Such services are called Stateless an can be deployed in luster easily.

However if you want to build Stateful Service, the only easy way to go is Workflow Foundation with enabled persistence. The only out-of-the-box possibility was to use Workflow Service. They can be span across multiple hosts very easy. In a case of WCF this is more complex task. To make this more clear, take a look on following WCF example, which illustrate how this will work in the future:

[Replicable]
public class MyStatfulService : IStatefulService
{

       [Replicable(false)]
        private string m_Field1;


        [Replicable]
        private string m_Field2;


        public string GetFieldValue()
        {
            return m_Field2;
        }

       

        [ReplicateOnExit]
        public void SetFieldValue(string fieldValue)
        {

            m_Field2 = fieldValue;
            m_Field1++;
        }
    }

This code snippet defines the stateful WCF service. It is important to make a difference between WCF Stateful Service and Task Scheduler Stateful Service. These are two currently supported Stateful Services.
First of all you will have to mark the service with attribute Replicable. This indicates the the runtime will ensure that required state of the service is replicated between running instances of the service.

Additionally by using of attribute you can control what fields are replicable and what not? For example Replicable(true) or just Replicable setup the field to be replicable. That means the new value of the field will be replicated between all instances of the service. With Replicable(false) you can explicitly exclude the field from replication.

In example above, field m_Field1 will not be replicated. Because of this the last line in the code m_Field1++ will have no effect. The default WCF service Behavior (if no any specified like above) use instance policy called InstanceContextMode.PerCall. In this case on every call to some service operation (like above) the new instance of the service will be created. For this reason m_Field1 would always be initialized at zero. Today developers just define this field as static one and ensure that the value is incremented by each call. This works fine as long your service is running at one machine only. In the world of cloud computing this should never be (but it could if you like) the case.
Imagine, you have two instances of the same service at two different machines. If m_Field1 would be the static variable, both instances would have its own counter. We want to have one single counter which has the same value on both machines.
To do that we can simple use  Stateful services. That is, we put attribute Replicable at the service class.

Last but not least, you can use attribute ReplicateOnExit to indicate that replication will be started after the operation exists.

Container Partitioning Policy

To make all this working you will have to setup the container properties properly. If you remember AppFabric Applications support a set of container, which can host different kind of services. Stateful Services are by default hosted in the StateFul Container. Switch to design view, select StatefulApPFabricContainer (this is where out service “MyStatefulService” is hosted). Note in property window the PartitionPolicy.
Currently there are to of them: Hash-based and Key-based.

 

image       image

 

Hash-policy

In this case the hash-based policy is used. You just have to set up the number of partitions you want for the stateful service group. The default value is 32. The client will by creating of the proxy specify additional parameter which will indicate which partition is used. This is simply some string value. You could use up to 32 (in this case) different strings.
This policy does not require any configuration and you can use any partition key as name in the proxy.

Fixed Key policy

This policy enables you to specify exactly the names of supported partitions. It is more complicated for setup, but it allows you to define more precisely partitions related to the business logic. Here is one example:

image

Select Fixed Key Partitioning policy and click on (Collection). Then enter any logical names of partitions. In my example I want to distinguish between states of two tenants. This is a great example of how to use one service deployment for multiple tenants.

And what now?

AT this moment your are probably asking yourself how all this work for real? To demonstrate this, I will create one web application. Remember this is now AppFabric Application service of type ASP.NET.
Following pictures show my application with one ASP.NET WebApp (hosted in web container) and MyStatefulService (stateful service hosted in statefulappfabric container).
imageimage

The ASP.NET application implements the very simple page like shown below. The service implements the code shown at the beginning of this post.

image

The application does following. I enter in the first textbox the name of partition (key1) and the value which I want to pass to operation SetFieldValue. The code behind will invoke the operation SetFieldValue(hello) when the button Put is clicked. The service will remember this value and replicate it to all other running instances after the operation SetFieldValue has ended (ReplicateOnExit ).
By clicking on button Get you  get the persisted state value form specified container. In this case the operation GetFieldValue will be invoked.

Get field value simply does following:

public string GetFieldValue()
{
    return m_Field2;
}

It just returns the value of field m_Field2. Because this field is configured for replication it will always be retrieved the value which is replicated to all running instances.

[Replicable]
private string m_Field2;

In fact you just implement you service as you always did. Then set few attributes and that’s it.

How to build the consumer of stateful service?

To build the consumer, you first have to add the reference from WebApp to MyStatefulService.  To do that don’t go Add Service References, Instead add reference by click on service reference in the diagram above (picture above shows one already added reference). After that Visual Studio will create the file ServiceReferences.g.cs with one helper class named ServiceReferences.

class ServiceReferences

{

        public staticIStatefulService CreateImport1(string partitionKey)

        {

            Return ResolveImport< IStatefulService>("Import1", partitionKey);
        }

 

        public static IStatefulService CreateImport1(string partitionKey,
                              Dictionary<string, object> contextProperties)
        {

            return ResolveImport<IStatefulService>("Import1",
                   partitionKey, contextProperties);
        }
  
}


In the code behind, I have implemented following:

  public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void m_Get_Click(object sender, EventArgs e)
        {
            string partitionKey = m_Key2.Text;

            var proxy = ServiceReferences.CreateImport1(partitionKey);

            m_Result.Text = proxy.GetData();
        }

        protected void m_Put_Click(object sender, EventArgs e)
        {
              string partitionKey = m_Key1.Text;

            var proxy = ServiceReferences.CreateImport1(partitionKey);

            proxy.SetData(m_Value.Text);        
        }
    }


Most important in this code is the way how to create the endpoint to service. The line of code

var
proxy = ServiceReferences.CreateImport1(partitionKey);

creates the initialized proxy instance. You don’t have to care about configuration, because this all is done for you during deployment process. The partitionKey defines the logical state set. Under one partition you can persist/replicate the whole set of states. So, one tenant would use partition key “Tenant1” and second tenant would use “Tenant2”. Both consumers for tenant1 and tenant2 would use the same service endpoint and even the same consumer code, but with different partition key. However the second is also the question of security. For example if the consumer is the javascript one could look in the code and gram the tenant. So be careful in design.


Hope this post helps to understand the world of new WCF type of services.

Damir


Posted Jul 17 2011, 12:46 PM by Damir Dobric
Filed under: , , ,

Comments

Damir Dobric Posts wrote AppFabric Applications - Episode VII: Distributed Task Scheduler
on 09-08-2011 1:00

The Task Scheduler Service is one of external services provided out-of-the-box by AppFabric Applications

DamirDobric wrote AppFabric Applications - Episode VII: Distributed Task Scheduler
on 09-08-2011 1:29

The Task Scheduler Service is one of external services provided out-of-the-box by AppFabric Applications

Damir Dobric Posts wrote AppFabric Applications - Episode VII: Distributed Task Scheduler
on 09-13-2011 23:21

The Task Scheduler Service is one of external services provided out-of-the-box by AppFabric Applications

Damir Dobric Posts wrote Introduction to AppFabric Applications
on 09-13-2011 23:25

Few weeks ago Microsoft has published the first public CTP related to Application Composition under the

developers.de is a .Net Community Blog powered by daenet GmbH.