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.
What we need
Basically we need to:
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.
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
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.
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
This comment has been removed by the author.
ReplyDelete