Building high quality services using Azure Service Fabric
Loek Duys
@LDuys
Introduction
No introduction to Service Fabric
Learn about partitioning
Creating testable code
Service Programming Model
PartitionsService
Types
Application
Types
App
Stateful
Svc
1
2
x
Stateless
Svc1
Why?
State
Number of partitions
Address space divided across partitions
PARTITION 1 PARTITION 2INT64 MIN INT64 MAX
PARTITION 4PARTITION 3PARTITION 2PARTITION 1
-9,223,372,036,854,775,808 9,223,372,036,854,775,807
Partitions vs. Nodes
Node 1
Primary
Replica 1
Secondary
Replica 2
Node 2
Primary
Replica 2
Secondary
Replica 1
Partition 1
Partition 2
Copy of partition 2
Copy of partition 1
Read + Write
Read only
Read + Write
Read only
Partitioning strategies
Monastery: Hand-written books
Order:
Write a dictionary (26.000 words)
Can span multiple books / volumes
Reader constraints:
Search max. one book for one word.
Writer constraints:
1. One monk writes one book (Service Fabric rule)
2. Average writing speed for monk, is 1.000 dictionary words per year
3. Monastery has 52 writing monks
The partitioning problem
Partition by first letter Consequences
Introduce a Librarian
Add/Lookup
wordLibrarian
Book 1
Book 2
Book ..
Book x
Add/Lookup
word
Index
service
Dictionary
Service
Partition 1
Dictionary
Service
Partition 2
Dictionary
Service
Partition ..
Dictionary
Service
Partition x
Introduce an index
Creating a good Index service
Good LibrarianMust distribute words evenly across the books.
So all books have similar page count.
So work load is equal for all monks
So you can add more monks & books
using 26 monks: done in 1 year
using 52 monks: done in 0.5 year
Good Index serviceMust distribute data evenly across the partitions.
So every partition holds same amount of data
So user load on partitions is equal
So your services can scale linearly
Inside Index Serviceuse proper hash algorithm
Example:
word hash number partition address
Outcome must be well distributed
Great choicesFNV
Murmur
Load distribution, using 4 partitions
good
bad
Attribute Result
Id User data in one partition
Organization Users grouped by Organization
Location Amsterdam data grouped
Attribute Result
Low distribution Uneven use of partitions
High
distribution
Even use of partitions
public class User { public int Id; public Organization Organization;public string Location;
}
Inside Cluster
On top of Cluster,
API management
solution
Dictionary Service
Partition 1
Dictionary Service
Partition 2
Index Service
Dictionary Service
Partition 1
Dictionary Service
Partition 2
Index Service in cluster
Index Service on top of cluster
API management
solution
Dictionary Service
Partition 1
Dictionary Service
Partition 2
Index Service
Dictionary Service
Partition 1
Dictionary Service
Partition 2
Identifier Service Instance
app1/dictionarysvc1 fabric:/application1/dictionaryservice1
app2/dictionarysvc10 fabric:/application2/dictionaryservice10
.. ..
Example: Web API
app1 dictionarysvc word=cloud
Partition
Service
Application
Create Backups
Failure is always an option
Human error
Cluster failure
Stateful Service backups work at partition level
Can restore to different Service
Little tooling available
Tips
Store backups outside the cluster
Check out my project ServiceFabric.BackupRestore
(Github & Nuget)
Contains tools that help create, restore and store backup data
Creating quality code
Difficulties while testing
Services expect to be running inside clusterStateManager
Service Fabric Remoting using Proxies
Cut dependenciesUse Dependency Injection pattern
Pass dependencies to Service constructor
Inject cluster based objects at run-time
Inject ‘fake’ objects at test-time (Mocks)
Index Service Dictionary Service
Dependency injection 1
How to test Dictionary Service State Tips
public DictionaryService(StatefulServiceContext context, IReliableStateManagerReplica2 stateManager): base(context, stateManager)
{..}
ServiceRuntime.RegisterServiceAsync("ServiceFabric.Dictionary.DictionaryServiceType", context => new DictionaryService(context,
new ReliableStateManager(context))).GetAwaiter().GetResult();
var dictionaryService = new DictionaryService(MockStatefulServiceContextFactory.Default,new MockReliableStateManager());
Dependency injection 2
How to test Index Service Communication
public IndexService(StatelessServiceContext context,IServiceProxyFactory serviceProxyFactory,IHashingHelper hashingHelper) : base(context)
{..}
ServiceRuntime.RegisterServiceAsync("ServiceFabric.Dictionary.IndexServiceType",context => new IndexService(context,
new ServiceProxyFactory(),new HashingHelper())
).GetAwaiter().GetResult();
//Configure Mock Service Proxy Factory to return the svc we //created on previous slidevar mockServiceProxyFactory = new MockServiceProxyFactory(); mockServiceProxyFactory.RegisterService(
dictionaryServiceUri,dictionaryService);
//inject mock proxy factoryvar indexService = new IndexService(
MockStatelessServiceContextFactory.Default,mockServiceProxyFactory,new MockHashingHelper());
Tips
Bringing it together
We can now
//arrange: not displayed
const string tesMeaning = "testmeaning"; const string testWord = "testword";
//actawait indexService.Add(testWord, testMeaning)
.ConfigureAwait(false);
var actual = await indexService.Lookup(testWord).ConfigureAwait(false);
//assertAssert.AreEqual(testMeaning, actual);
var proxy = ServiceProxy.Create<IDictionaryService>(
DictionaryServiceUri,partitionKey);
var proxy = _dictionaryServiceProxyFactory.CreateServiceProxy<IDictionaryService>(
DictionaryServiceUri,partitionKey);
Building Actor systems with Azure Service Fabric
Azure API management usage in practice
Codehttps://github.com/loekd/ServiceFabric.Dictionary
Pictures courtesy of https://unsplash.comhttps://pexels.comhttps://gratisography.com
Building Actor systems with Azure Service Fabric
Today at 14:00 E102 - Sander Molenkamp
Azure API management usage in practice
Tomorrow at 08:00 E104/105 - Chris van Sluijsveld
https://github.com/loekd/ServiceFabric.Dictionary