Service Fabric Notes
Khaled Hikmat
Software EngineerI am compiling notes when working with Service Fabric from the folks at Microsoft! In this post, I will enumerate a few things that I ran into which I think might be helpful to others who are learning the environment as well. This will not be a complete list ....so I will add to it as I go along.
#
Actor Turn-based ConcurrencyActors are single threaded! They only allow one thread to be acting on them at any given time. In fact, in the Service Fabric terminology, this is referred to as Turn-based treading. From my observation, it seems that this is how the platform and the actors
What happens to the clients who are calling the actors? If two clients are trying to access an actor at the same time, one blocks until the actor finishes the first client method. This is to ensure that an actor works on one thing at a time.
Let us say, we have an actor that has two methods like this:
If you call GetThing1
from one client and immediately call GetThing2
from another client (or Postman session), the second client will wait at least 15 seconds to get the string thing2
response.
Given this:
- I think it is best to front-end actors with a service that can invoke methods on actors when it receives requests from a queue. This way the service is waiting on actors to complete processing while it is in its
RunAsync
method. - It is important to realize that actors should really not be queried and that actors should employ several things:
- Backup state to an external store such as DocumentDB or others. This way the external store can be queried instead.
- Aggregate result externally perhaps via Azure Function into some outside store so queries could run against this store
- Aggregate result to an aggregator actor that can quickly respond to queries which will relieve the processing actors from worrying about query requests.
#
Actor RemindersActor Reminders are really nice to have. In the sample app that I am working on, I use them to schedule processing after I return to the caller. Effectively they seem to give me the ability to run things asynchronously and return to the caller right away. Without this, the actor processing throughput may not be at best if the the processing takes a while to complete.
In addition to firing a future event, they do allow me to pack an item or object that can be retrieved when the reminder triggers. This makes a lot of scenarios possible because we are able to pack the item that we want the reminder to work on.
Please note, however, that when a reminder is running in an actor, that actor cannot respond to other method invocation! This is because the platform makes sure that there is only a single threaded operating on an actor at any time.
The best way I found out to schedule reminders to fire immediately is something like this:
When the reminder triggers, ReprocessReminder
is called to process the item that was packed within the reminder: ObjectToByteArray(item)
. Here are possible implementation of packing and unpacking the item:
#
Actor InterfaceFrom this article: The arguments of all methods, result types of the tasks returned by each method in an actor interface, and objects stored in an actor's State Manager must be Data Contract serializable. This also applies to the arguments of the methods defined in actor event interfaces. (Actor event interface methods always return void.)
In my actor interface, I had many methods and everything was working great until I added these two methods:
If you to compile a Service Fabric solution that has an interface that looks like the above, you will be met with a very strange compilation error:
What? What is that? Why? After hours, it turned out you can actually turn off this error. From the above Stack Overflow post:
By changing the project file .csproj of the project containing the actors and setting property:
So this tool can be disabled!! But still why is this happening? It turned out that the actor interfaces may not have overridden methods!! So the tool was complaining about the interface containing just that i.e. overridden methods. If the above interface is changed to the below, everything will work well:
In addition, the actor event methods may not return anything but void
. So if you have something like this, you will get the same FabActUtil.exe
error:
I am hoping to add to this post as I go along. Hopefully this has been helpful.