- Build & manage scalable and reliable microservices that on clusters
- cluster = a shared pool of machines
- Runtime
- build distributed, scalable, stateless, and stateful microservices running in containers.
- Management
- Deploy, monitor, upgrade/patch, and delete deployed applications including containerized services
- You can choose to use ASP.NET Core programming models, or can just deploy and manage containers with Service Fabric container orchestrator.
- Applications are resource-balanced across virtual machines to maximize efficiency.
- Uses cases e.g. real-time data analysis, in-memory computation, parallel transactions, and event processing in your applications
- Scale with partitioned storage
- Can have dependencies to caches, storages, queues etc., but they're external services.
- As opposed to stateful applications have internal states in them e.g. databases, storages etc.
- Can have dependencies to caches, storages, queues etc., but they're external services.
- Increase reliability with queues
- Reduce read latency with caches
- Write your own lock managers for state consistency
- Maintain state reliably within the service itself, co-located with the code that's using it.
- Application state lives in the compute tier.
- Low latency reads & writes
- Partitions are first class for scale-out
- Built in lock managers based on primary election
- E.g. Azure Cloud Service worker roles
- High availability and consistency of the state
- through simple APIs that provide transactional guarantees backed by replication
- available by Service Fabric without external store.
- Applications can have their "hot" state and data managed within them for additional performance gains without sacrificing reliability, consistency, or availability
- They're deployed into same Service Fabric cluster with their dependencies.
- Each of these services is independent with regard to scale, reliability, and resource usage, greatly improving agility in development and lifecycle management.
- Simplify application designs: They remove the need for the additional queues and caches that have traditionally been required to address the availability and latency requirements of purely stateless applications.
- Service type
- Service implementation.
- Defined by class that extends
StatelessService
- Has name and a version number
- Named service instance
- An URI using
fabric:/
scheme e.g.fabric:/MyApp/MyService
- An URI using
- Service host
- Instances that needs to run inside a host process.
- Service registration
- The service type must be registered with the Service Fabric runtime in a service host
- Allows Service Fabric to create instances of it to run.
-
Install the Service Fabric runtime, SDK, and tools.
-
Enable execution of the Windows PowerShell scripts included in the SDK.
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force -Scope CurrentUser
- New project => Service Fabric Application => Name it
HelloWorld
- .NET Core => StatelessService => Name it
HelloWorldStateless
- Your solution now contains two projects:
HelloWorld
- Application project
- Contains services and some PowerShell scripts that help you to deploy your application.
HelloWorldStateless
- Service project
- Contains stateless service implementation.
- In service project (
HelloWorldStateless.cs
) you run any business logic. - Two entry points:
-
Open-ended entry point
-
You begin executing workloads, including long-running compute workloads.
protected override async Task RunAsync(CancellationToken cancellationToken) { // ... }
-
A cancellation token is provided to coordinate when your service instance needs to be closed.
-
Cancellation is requested when:
- The system moves your service instances for resource balancing.
- Faults occur in your code.
- The application or system is upgraded.
- The underlying hardware experiences an outage.
-
The system will wait for your task to end (by successful completion, cancellation, or fault) before it moves on.
- It is important to honor the cancellation token, finish any work, and exit
RunAsync()
as quickly as possible when the system requests cancellation.
- It is important to honor the cancellation token, finish any work, and exit
-
-
A communication entry point
- You can plug in your communication stack of choice, e.g. start receiving requests (e.g. via ASP .NET Core) from users and other services.
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners() { // ... }
-
- Add -> New Service Fabric Service -> Name it
HelloWorld
- .NET Core -> Stateful Service and name it
HelloWorldStateful
- The main difference is the availability of a state provider that can store state reliably.
- State provider implementation called Reliable Collections.
- Lets you create replicated data structures through the Reliable State Manager.
- Operations are transactional = consistent everywhere
- Stores your data to local disk on each replica.
- Transactions are atomic
- You may dequeue a work item from a
Reliable Queue
, perform an operation on it, and save the result in aReliable Dictionary
, all within a single transaction.
- You may dequeue a work item from a
- A stateful Reliable Service uses this state provider by default.
- You can store data directly in your service without the need for an external persistent store.
- Lets you create replicated data structures through the Reliable State Manager.
-
A stateful service has the same entry points as a stateless service.
- In a stateful service, the platform performs additional work on your behalf before it executes
RunAsync()
. This work can include ensuring that the Reliable State Manager and Reliable Collections are ready to use.
- In a stateful service, the platform performs additional work on your behalf before it executes
-
Code example:
protected override async Task RunAsync(CancellationToken cancellationToken) { var myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, long>>("myDictionary"); while (true) { cancellationToken.ThrowIfCancellationRequested(); using (var tx = this.StateManager.CreateTransaction()) { var result = await myDictionary.TryGetValueAsync(tx, "Counter"); ServiceEventSource.Current.ServiceMessage(this.Context, "Current Counter Value: {0}",result.HasValue ? result.Value.ToString() : "Value does not exist."); await myDictionary.AddOrUpdateAsync(tx, "Counter", 0, (key, value) => ++value); // If an exception is thrown before calling CommitAsync, the transaction aborts, all changes are discarded, and nothing is saved to the secondary replicas. await tx.CommitAsync(); } await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); }