Skip to main content

(Part 2) Azure Service Fabric - Parent Child communication and cancellation

Part 1 - http://vunvulearadu.blogspot.ro/2016/03/azure-service-fabric-parent-child.html

Part 2 - http://vunvulearadu.blogspot.ro/2016/03/part-2-azure-service-fabric-parent.html

Solution 1 for the below problem can be found here: http://vunvulearadu.blogspot.ro/2016/03/azure-service-fabric-parent-child.html.

A few weeks ago I so an interesting question on MSDN forum that I think that is pretty common. In this post I will try to give a possible solution to this problem.

Context:
There are multiple instances of the same Restful Stateful Services that are running in parallel. A new instance is created by a 'parent service that also might specifies the action that needs to be executed.
Problem:
The parent service needs to be able to cancel the instance of our Restful Stateless Service based on external factors or based on the current state of the child.


What we need
Basically we need to:

  • Store and map all the service instances that are created by a service
  • Store in a specific location a state related to them
  • Share their state with the parent service
  • Give the ability to the parent to cancel a child service

Solution
The first solution was based on Reliable Collection that allowed us to communicate between parent and child instance. 
The solution is great, but has a big drawback. Parent and child instance type needs to be the same. This means that you will have only a type of service that needs to know to do the logic of the child, but also it has to have the logic used to manage the children's.
  
To be able to split the logic in two different services we would need a mechanism that would allow us to communicate between the instance of our child service and our parent service. 
If we would have Actors ad not Reliable Services, we would use events. Using them we would be able to notify the Parent instances when the instance state would change. Reliable Service doesn't have support for this kind of events.
In this context we need to find a different way to communicate. Of course for cases like this we can go with a classic approach and use:
  • Azure Service Bus Queue - send the change state of a child service to parent
  • Azure Service Bus  Topic - send the change state of a child service to parent
  • Azure Queue - send the change state of a child service to parent
  • Azure Table - store the child state, where child service instance update his state and Parent reads the state when needed
  • Azure Redis Cache or other types of services
Of course we could use any kind of storage or messaging solution to communicate between them. But the problem for all this solution is with the location where we need to make the call. For all of them, we are using an external service that will trigger an external call. Do we really need to use an external storage/messaging solution? 
A solution like this would increase the complexity of our system, maintenance costs, running cost and even it would affect our performance with the latency of our external call.


The real solution
A useful feature of Azure Service Fabric that can be used to resolve our problem is Service Remoting - basically we can call remotely a method of our service. 
In this moment we have two approaches:
  • Expose a method in the child service that would allow parent service us to get the state
  • Expose a method in the parent service that would be called by child service instance each time when the state change
If we would go with the first approach we would need to call all instances of child service at a specific time interval to get the state and if the state was change to update the state mapping or execute a specific action.
We might not be updated soon enough when state change. In the context of long running tasks, we might not need to query the state very often because the state is not changing frequently. The good part of this approach is that the child service doesn't need to have any information about the parent. The parent knows the 'address' of the child and calls him.

The second approach requires from us to expose a method on the parent service that can be called by child service each time when the state change. In this way we will be notified as soon as possible when the the state of a child instance service change.
This is a good approach, but you might have problems if the number of child instances is very high or the state changes very often.

Selected solution
The problem that was described at the beginning of the post was for long running task on child service, where the state is not changing very often.
In this context, I would go and prefer the second solution, where the child services calls the parent each time when the state change.
The downside of this solution is that each child needs to know the address of the parent. This address can be specified in the parameters list in the moment when child is created or a new 'order' is send to him.
The parent service can store and map all the information related to the child services in a reliable collection - Reliable Dictionary might be a good starting point.

Service Remoting Sample
I will write next week how we can do Service Remoting and how does it work. Let's only take a look on how we can call and expose a method of a service that can be called from another service.

Uri statefulServiceUri = new Uri(@"fabric:/Demo.SF/ParentService");
IParentStatefullService parentServiceProxy = 
  ServiceProxy.Create<IParentStatefullService>(1, statefulServiceUri);
parentServiceProxy.StateChange(childId,newState);


In the above example, based on an URI we make a remote call to our parent service. As we can see to make  a basic remote call is very simple. The magic number  1 represents the partition number. In our case we have only one instance of our service in only one partition.

protected override async Task RunAsync(CancellationToken cancelServiceInstance)
{ 
  ...
  
  // State is change, we need to notify our parent.
  Uri statefulServiceUri = new Uri(parentServiceAddress);
  IParentStatefullService parentServiceProxy = 
    ServiceProxy.Create<IParentStatefullService>
      (parentServicePartitionNumber, statefulServiceUri);
  parentServiceProxy.StateChange(childId,newState);
  
  ...
}

Final conclusion
In this post we found two different approaches to establish a communication channel between Parent and Child Services. There is not best solution solution for any use case.
Based on our requirements and constrains we should be able to select the solution that suites our needs.

Part 1 - http://vunvulearadu.blogspot.ro/2016/03/azure-service-fabric-parent-child.html
Part 2 - http://vunvulearadu.blogspot.ro/2016/03/part-2-azure-service-fabric-parent.html

Comments

Post a Comment

Popular posts from this blog

How to check in AngularJS if a service was register or not

There are cases when you need to check in a service or a controller was register in AngularJS.
For example a valid use case is when you have the same implementation running on multiple application. In this case, you may want to intercept the HTTP provider and add a custom step there. This step don’t needs to run on all the application, only in the one where the service exist and register.
A solution for this case would be to have a flag in the configuration that specify this. In the core you would have an IF that would check the value of this flag.
Another solution is to check if a specific service was register in AngularJS or not. If the service was register that you would execute your own logic.
To check if a service was register or not in AngularJS container you need to call the ‘has’ method of ‘inhector’. It will return TRUE if the service was register.
if ($injector.has('httpInterceptorService')) { $httpProvider.interceptors.push('httpInterceptorService&#…

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine:
threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration:

TeamCity.NET 4.51EF 6.0.2VS2013
It seems that there …

[Post-Event] Codecamp Conference Cluj-Napoca - Nov 19, 2016

Last day I was invited to another Codecamp Conference, that took place in Cluj-Napoca. Like other Codecamp Conferences, the event was very big, with more than 1.000 participants and 70 sessions. There were 10 tracks in parallel, so it was pretty hard to decide at  what session you want to join.
It was great to join this conference and I hope that you discovered something new during the conference.
At this event I talked about Azure IoT Hub and how we can use it to connect devices from the field. I had a lot of demos using Raspberry PI 3 and Simplelink SensorTag. Most of the samples were written in C++ and Node.JS and people were impressed that even if we are using Microsoft technologies, we are not limited to C# and .NET. World and Microsoft are changing so fast. Just looking and Azure IoT Hub and new features that were launched and I'm pressed (Jobs, Methods, Device Twin).
On backend my demos covered Stream Analytics, Event Hub, Azure Object Storage and DocumentDB.

Title:
What abo…