title: Service Fabric Hosting

Service Fabric Hosting

Orleans can be hosted on Service Fabric using the Microsoft.Orleans.Hosting.ServiceFabric package. Silos should be hosted as unpartitioned, stateless services since Orleans manages distribution of grains itself using fine-grained, dynamic distribution. Other hosting options (partitioned, stateful) are currently untested and unsupported.

A sample which demonstrates hosting on Service Fabric is available at Samples/2.0/ServiceFabric.

Hosting support is available in the Microsoft.Orleans.Hosting.ServiceFabric package. It allows an Orleans Silo to run as a Service Fabric ICommunicationListener. The Silo lifecycle follows the typical communication listener lifecycle: it is initialized via the ICommunicationListener.OpenAsync method and is gracefully terminated via the ICommunicationListener.CloseAsync method or abruptly terminated via the ICommunicationListener.Abort method.

Official clustering support is available from various packages including:

  • Microsoft.Orleans.Clustering.AzureStorage
  • Microsoft.Orleans.Clustering.AdoNet
  • Microsoft.Orleans.Clustering.DynamoDB

There are also several third-party packages available for other services such as CosmosDB, Kubernetes, Redis and Aerospike. More information about cluster management can be found here. This example makes use of the Microsoft.Orleans.Clustering.AzureStorage package to utilize Azure Storage.

OrleansCommunicationListener provides the ICommunicationListener implementation. The recommended approach is to create the communication listener using OrleansServiceListener.CreateStateless(Action<StatelessServiceContext, ISiloHostBuilder> configure) in the Orleans.Hosting.ServiceFabric namespace.

Each time the communication listener is opened, the configure delegate passed to CreateStateless is invoked to configure the new Silo.

Example: Configuring Service Fabric hosting

The following example demonstrates a Service Fabric StatelessService class which hosts an Orleans silo. The full sample can be found in the Samples/2.0/ServiceFabric directory of the Orleans repository.

  1. /// <summary>
  2. /// An instance of this class is created for each service instance by the Service Fabric runtime.
  3. /// </summary>
  4. internal sealed class StatelessCalculatorService : StatelessService
  5. {
  6. public StatelessCalculatorService(StatelessServiceContext context)
  7. : base(context)
  8. {
  9. }
  10. /// <summary>
  11. /// Optional override to create listeners (e.g., TCP, HTTP) for this service replica to handle
  12. /// client or user requests.
  13. /// </summary>
  14. /// <returns>A collection of listeners.</returns>
  15. protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
  16. {
  17. // Listeners can be opened and closed multiple times over the lifetime of a service instance.
  18. // A new Orleans silo will be both created and initialized each time the listener is opened
  19. // and will be shutdown when the listener is closed.
  20. var listener = OrleansServiceListener.CreateStateless(
  21. (fabricServiceContext, builder) =>
  22. {
  23. builder.Configure<ClusterOptions>(options =>
  24. {
  25. // The service id is unique for the entire service over its lifetime. This is
  26. // used to identify persistent state such as reminders and grain state.
  27. options.ServiceId = fabricServiceContext.ServiceName.ToString();
  28. // The cluster id identifies a deployed cluster. Since Service Fabric uses rolling
  29. // upgrades, the cluster id can be kept constant. This is used to identify which
  30. // silos belong to a particular cluster.
  31. options.ClusterId = "development";
  32. });
  33. // Configure clustering. Other clustering providers are available, but for the purpose
  34. // of this sample we will use Azure Storage.
  35. // TODO: Pick a clustering provider and configure it here.
  36. builder.UseAzureStorageClustering(
  37. options => options.ConnectionString = "UseDevelopmentStorage=true");
  38. // Optional: configure logging.
  39. builder.ConfigureLogging(logging => logging.AddDebug());
  40. builder.AddStartupTask<StartupTask>();
  41. // Service Fabric manages port allocations, so update the configuration using those
  42. // ports.
  43. // Gather configuration from Service Fabric.
  44. var activation = fabricServiceContext.CodePackageActivationContext;
  45. var endpoints = activation.GetEndpoints();
  46. // These endpoint names correspond to TCP endpoints specified in ServiceManifest.xml
  47. var siloEndpoint = endpoints["OrleansSiloEndpoint"];
  48. var gatewayEndpoint = endpoints["OrleansProxyEndpoint"];
  49. var hostname = fabricServiceContext.NodeContext.IPAddressOrFQDN;
  50. builder.ConfigureEndpoints(hostname, siloEndpoint.Port, gatewayEndpoint.Port);
  51. // Add your application assemblies.
  52. builder.ConfigureApplicationParts(parts =>
  53. {
  54. parts.AddApplicationPart(typeof(CalculatorGrain).Assembly).WithReferences();
  55. // Alternative: add all loadable assemblies in the current base path
  56. // (see AppDomain.BaseDirectory).
  57. parts.AddFromApplicationBaseDirectory();
  58. });
  59. });
  60. return new[] { listener };
  61. }
  62. /// <summary>
  63. /// This is the main entry point for your service instance.
  64. /// </summary>
  65. /// <param name="cancellationToken">
  66. /// Canceled when Service Fabric needs to shut down this service instance.
  67. /// </param>
  68. protected override async Task RunAsync(CancellationToken cancellationToken)
  69. {
  70. while (true)
  71. {
  72. cancellationToken.ThrowIfCancellationRequested();
  73. await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
  74. }
  75. }
  76. }