Back to Blog
2 min read

Azure Service Fabric: Microservices Platform

Service Fabric is Microsoft’s battle-tested microservices platform. Powers Azure SQL, Cosmos DB, and Cortana. Now available for your workloads.

Service Types

Stateless Services

internal sealed class WebApi : StatelessService
{
    public WebApi(StatelessServiceContext context) : base(context) { }

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new[]
        {
            new ServiceInstanceListener(context =>
                new KestrelCommunicationListener(context, "ServiceEndpoint", (url, listener) =>
                    WebHost.CreateDefaultBuilder()
                        .UseStartup<Startup>()
                        .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl)
                        .UseUrls(url)
                        .Build()))
        };
    }
}

Stateful Services

internal sealed class OrderService : StatefulService
{
    public OrderService(StatefulServiceContext context) : base(context) { }

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        var orders = await StateManager.GetOrAddAsync<IReliableDictionary<string, Order>>("orders");

        while (!cancellationToken.IsCancellationRequested)
        {
            using var tx = StateManager.CreateTransaction();

            var pendingOrders = await orders.CreateEnumerableAsync(tx);
            var enumerator = pendingOrders.GetAsyncEnumerator();

            while (await enumerator.MoveNextAsync(cancellationToken))
            {
                var order = enumerator.Current.Value;
                if (order.Status == OrderStatus.Pending)
                {
                    await ProcessOrder(order, tx);
                }
            }

            await tx.CommitAsync();
            await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
        }
    }
}

Actor Model

[ActorService(Name = "OrderActorService")]
[StatePersistence(StatePersistence.Persisted)]
public class OrderActor : Actor, IOrderActor
{
    public OrderActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId) { }

    public async Task<Order> GetOrderAsync()
    {
        return await StateManager.GetStateAsync<Order>("order");
    }

    public async Task UpdateStatusAsync(OrderStatus status)
    {
        var order = await StateManager.GetStateAsync<Order>("order");
        order.Status = status;
        await StateManager.SetStateAsync("order", order);
    }
}

// Client usage
var actorId = new ActorId(orderId);
var orderActor = ActorProxy.Create<IOrderActor>(actorId, new Uri("fabric:/MyApp/OrderActorService"));
await orderActor.UpdateStatusAsync(OrderStatus.Shipped);

Application Manifest

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyAppType" ApplicationTypeVersion="1.0.0">
  <Parameters>
    <Parameter Name="WebApi_InstanceCount" DefaultValue="-1" />
    <Parameter Name="OrderService_PartitionCount" DefaultValue="5" />
  </Parameters>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="WebApiPkg" ServiceManifestVersion="1.0.0" />
  </ServiceManifestImport>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="OrderServicePkg" ServiceManifestVersion="1.0.0" />
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="WebApi">
      <StatelessService ServiceTypeName="WebApiType" InstanceCount="[WebApi_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <Service Name="OrderService">
      <StatefulService ServiceTypeName="OrderServiceType" TargetReplicaSetSize="3" MinReplicaSetSize="2">
        <UniformInt64Partition PartitionCount="[OrderService_PartitionCount]" LowKey="0" HighKey="100" />
      </StatefulService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

Deployment

# Connect to cluster
sfctl cluster select --endpoint https://mycluster.eastus.cloudapp.azure.com:19080

# Deploy application
sfctl application upload --path ./MyAppPackage
sfctl application provision --application-type-build-path MyAppPackage
sfctl application create --app-name fabric:/MyApp --app-type MyAppType --app-version 1.0.0

Health Monitoring

// Report health
var healthInfo = new HealthInformation("OrderService", "ProcessingStatus", HealthState.Ok)
{
    Description = "Processing orders normally",
    TimeToLive = TimeSpan.FromMinutes(5)
};
Partition.ReportInstanceHealth(healthInfo);

Service Fabric: enterprise microservices with built-in state management.

Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.