Skip to main content

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

Part 1 -

Part 2 -

Solution 1 for the below problem can be found here:

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.

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.
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

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);

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 = 
      (parentServicePartitionNumber, statefulServiceUri);

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 -
Part 2 -


Post a Comment

Popular posts from this blog

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 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 …

Entity Framework (EF) TransactionScope vs Database.BeginTransaction

In today blog post we will talk a little about a new feature that is available on EF6+ related to Transactions.
Until now, when we had to use transaction we used ‘TransactionScope’. It works great and I would say that is something that is now in our blood.
using (var scope = new TransactionScope(TransactionScopeOption.Required)) { using (SqlConnection conn = new SqlConnection("...")) { conn.Open(); SqlCommand sqlCommand = new SqlCommand(); sqlCommand.Connection = conn; sqlCommand.CommandText = ... sqlCommand.ExecuteNonQuery(); ... } scope.Complete(); } Starting with EF6.0 we have a new way to work with transactions. The new approach is based on Database.BeginTransaction(), Database.Rollback(), Database.Commit(). Yes, no more TransactionScope.
In the followi…

GET call of REST API that contains '/'-slash character in the value of a parameter

Let’s assume that we have the following scenario: I have a public HTTP endpoint and I need to post some content using GET command. One of the parameters contains special characters like “\” and “/”. If the endpoint is an ApiController than you may have problems if you encode the parameter using the http encoder.
using (var httpClient = new HttpClient()) { httpClient.BaseAddress = baseUrl; Task<HttpResponseMessage> response = httpClient.GetAsync(string.Format("api/foo/{0}", "qwert/qwerqwer"))); response.Wait(); response.Result.EnsureSuccessStatusCode(); } One possible solution would be to encode the query parameter using UrlTokenEncode method of HttpServerUtility class and GetBytes method ofUTF8. In this way you would get the array of bytes of the parameter and encode them as a url token.
The following code show to you how you could write the encode and decode methods.