Azure Service Fabric - Code Walkthrough For Stateless Reliable Service - Part Five

Introduction

 
In the first article of this series, we had a brief overview of Microservices architecture and Azure Service Fabric. Then, in the second article, we explored different programming models for Azure Service Fabric. We had a walkthrough of Reliable Services, Reliable Actors, Guest Executables, Containers and ASP.NET Core models for Service Fabric. In the third article, we had a good understanding of a couple of basic concepts in the Azure Service Fabric world like Clusters, Partitions, Replicas, and Instances. In the fourth article, we created a Reliable Services Stateless Service Fabric application using Visual Studio and hosted it in the local Service Fabric Cluster Manager. Below are the links for the previous articles in this series. As a prerequisite, it would be a good idea to go through these articles before proceeding ahead here.
In this article, we will deep dive into the Stateless Reliable Service that we created in the last article.
 

Codebase Walkthrough

 
When we created the application in Visual Studio, two projects got created as we can see in the Solution Explorer.
 
 
ReliableServicesStatelessDemo project manages all the operational aspects of the application. This can be treated as the project that supports the hosting infrastructure for the Service Fabric application. All configurational aspects like the number of nodes, instances, and other essential configurations are managed here. The deployment to the cluster is facilitated using a PowerShell script that got auto generated when created this application. Developers can incorporate all operational aspects here.
 
StatelessServiceForDemo is the actual Service Fabric project. It has the entry point to the application and the Web API controller for the Service Fabric. Developers need to focus to incorporate their requirements.
 

Understanding ReliableServicesStatelessDemo project

 
As we discussed in the previous section this project handles all operational aspects of the application. Let us get deep into this project.
 
 
This entire source code is structured in four folders - ApplicationPackageRoot ,ApplicationParameters, PublishProfiles, Scripts.
 
ApplicationPackageRoot contains the manifest file for the application named as ApplicationManifest.xml. All necessary configurations are defined. This manifest file has a parameters section where the default parameters are defined. However, the values for these parameters get overridden by the values from the parameters file in the ApplicationParameters folder.
  1. <Parameters>  
  2.    <Parameter Name="StatelessServiceForDemo_ASPNETCORE_ENVIRONMENT" DefaultValue="" />  
  3.    <Parameter Name="StatelessServiceForDemo_InstanceCount" DefaultValue="-1" />  
  4. </Parameters>  
Instance count is configured in the Service section. Name in the Service tag specifies the name of the Service Fabric application.
  1. <Service Name="StatelessServiceForDemo" ServicePackageActivationMode="ExclusiveProcess">  
  2.    <StatelessService ServiceTypeName="StatelessServiceForDemoType" InstanceCount="[StatelessServiceForDemo_InstanceCount]">  
  3.       <SingletonPartition />  
  4.    </StatelessService>  
  5. </Service>  
ApplicationParameters folder contains the parameter files. There are three parameters file – Cloud.xml, Local.1Node.xml and Local.5Node.xml. One of these parameter file can be loaded in the service fabric cluster. The parameter values specified here gets applied in the manifest file in the ApplicationPackageRoot folder. Let us examine one of these parameter file.
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.    <Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/ReliableServicesStatelessDemo" xmlns="http://schemas.microsoft.com/2011/01/fabric">  
  3.    <Parameters>  
  4.       <Parameter Name="StatelessServiceForDemo_ASPNETCORE_ENVIRONMENT" Value="Development" />  
  5.       <Parameter Name="StatelessServiceForDemo_InstanceCount" Value="1" />  
  6.    </Parameters>  
  7. </Application>  
PublishProfilesfolder contains the publishing profile for this application. Corresponding parameters file is specified exclusively in the publish profile. One of the publish profile can be chosen for deploying application to the cluster.
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.    <PublishProfile xmlns="http://schemas.microsoft.com/2015/05/fabrictools">  
  3.       <!-- ClusterConnectionParameters allows you to specify the PowerShell parameters to use when connecting to the Service Fabric cluster.  
  4.       Valid parameters are any that are accepted by the Connect-ServiceFabricCluster cmdlet.  
  5.       For a local cluster, you would typically not use any parameters.  
  6.       For example: <ClusterConnectionParameters />  
  7.       -->  
  8.    <ClusterConnectionParameters />  
  9. <ApplicationParameterFile Path="..\ApplicationParameters\Local.1Node.xml" />  
  10. </PublishProfile>  
The Scripts folder contains the deployment script - Deploy-FabricApplication.ps1 that facilitates actual deployment to the cluster.
 

Understanding StatelessServiceForDemo project

 
This is the project where the developer should focus on implementing the actual service. This is basically a WebAPI project.
 
 
The controllers can be defined in the Controllers folder with all necessary code. By default, ValuesController is generated when the application is created.
 
Program.cs is the most important file in the entire project. The Main method in this file is the entry point for the project. RegisterServiceAsync method registers the service and executes same.
  1. private static void Main() {  
  2.     try {  
  3.         // The ServiceManifest.XML file defines one or more service type names.  
  4.         // Registering a service maps a service type name to a .NET type.  
  5.         // When Service Fabric creates an instance of this service type,  
  6.         // an instance of the class is created in this host process.  
  7.         ServiceRuntime.RegisterServiceAsync("StatelessServiceForDemoType", context => new StatelessServiceForDemo(context)).GetAwaiter().GetResult();  
  8.         ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(StatelessServiceForDemo).Name);  
  9.         // Prevents this host process from terminating so services keeps running.  
  10.         Thread.Sleep(Timeout.Infinite);  
  11.     } catch (Exception e) {  
  12.         ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());  
  13.         throw;  
  14.     }  
  15. }  
When the application starts up CreateServiceInstanceListeners method gets called from the StatelessServiceForDemo class in StatelessServiceForDemo.cs file. This method does the actual trick of creating a service listener using Kestrel in this case. Other listeners can also be incorporated here.
  1. protected override IEnumerable < ServiceInstanceListener > CreateServiceInstanceListeners() {  
  2.     return new ServiceInstanceListener[] {  
  3.         new ServiceInstanceListener(serviceContext => new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) => {  
  4.             ServiceEventSource.Current.ServiceMessage(serviceContext, $ "Starting Kestrel on {url}");  
  5.             return new WebHostBuilder().UseKestrel().ConfigureServices(services => services.AddSingleton < StatelessServiceContext > (serviceContext)).UseContentRoot(Directory.GetCurrentDirectory()).UseStartup < Startup > ().UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None).UseUrls(url).Build();  
  6.         }))  
  7.     };  
  8. }  
All service events can be handled in ServiceEventSource.cs file.
 

Winding-up

 
In this article, we had a code walkthrough of the Reliable Stateless Service Fabric Application we created in the last article. We will create a Reliable Stateful Service Fabric Application in the next article of this series.