Anthony Chu Contact Me

Running Service Fabric Guest Executables with Dynamic Ports

Tuesday, February 13, 2018

Service Fabric can dynamically assign ports to a service. For stateless and stateful services, the Service Fabric SDK makes it easy to configure our services to listen to the dynamically assigned ports. But what about guest executables, especially ones that are precompiled and we cannot or do not want to modify the source code?

We'll look at how to configure ports for two sample Windows guest applications without modifying the source code:

  • A Go application that takes a port number as a command line argument
  • A self-contained ASP.NET Core application that can be configured using the ASPNETCORE_URLS environment variable

Windows containers

Service Fabric supports containers. If we're in an environment where containers can be used, an easy way to solve this problem is to package our applications in Windows containers. We can configure the application to listen to a specific port inside the container, and Service Fabric will take care of mapping its assigned port to the container port.

For more information on how to configure ports for containers in Service Fabric, check out this article.

Startup batch files

If we can't put the applications into containers, we'll need a way to run them as Service Fabric guest executables and configure ports at runtime. One way to solve this is with a startup batch file.

When a Service Fabric application starts up, the runtime sets a bunch of environment variables that the process can use to configure itself. The port is found in a variable named Fabric_Endpoint_<ServiceEndpointName>. For instance, if the service endpoint is named HelloGoSvcTypeEndpoint (in ServiceManifest.xml), its assigned port can be found in the environment variable named Fabric_Endpoint_HelloGoSvcTypeEndpoint.

The samples used in the remainder of this article can be found on GitHub.

Go app with command line arguments

Our first example is a Go web application that allows overriding of the port using a command line argument (-port). The source code can be found here.

To build the application, simply run go build in the hello-golang folder. An executable named hello-golang.exe will be produced in the same folder.

If we open the ServiceFabricApps solution and look at the service manifest of the HelloGo app, we can see that the service is configured without a specific port. This means a port will be assigned by Service Fabric at runtime.

<Endpoints>
    <Endpoint Name="HelloGoSvcTypeEndpoint" Protocol="http" Type="Input" />
</Endpoints>

And if we take a look at the entry point, we'll see that instead of running hello-golang.exe, it is configured to run a batch file named start.bat.

<EntryPoint>
    <ExeHost>
    <Program>start.bat</Program>
    <Arguments></Arguments>
    <WorkingFolder>CodeBase</WorkingFolder>
    </ExeHost>
</EntryPoint>

start.bat is simple:

.\hello-golang.exe -port=%Fabric_Endpoint_HelloGoSvcTypeEndpoint%

We use the batch file to extract the port from the environment variable we discussed earlier and pass it to the app as an argument.

To test this out, we right-click on the HelloGo project and select publish to the local cluster. This will import the hello-golang application, build the Service Fabric application package, and deploy it to our local Service Fabric cluster. Once deployment is complete, use the Service Fabric Explorer to find the port number (drill down to the application > service > partition > node > details, until you find endpoint information).

Note: The Service Fabric Explorer for the local cluster can usually be found at http://localhost:19080/Explorer/.

And open the browser to see the application working.

ASP.NET Core web app

For an ASP.NET Core web application, we can override the port by setting an environment variable named ASPNETCORE_URLS. To do this, we'll use the same batch file technique as we did with the Go app.

The ASP.NET Core app is found in the hello-aspnetcore folder. To build it, go to the folder and run dotnet publish -o out -r win-x64 --self-contained. This will create a folder named out with everything we need to run the application.

Back in the ServiceFabricApps solution, look at the service manifest of the HelloAspnet application. Like the Go version, it is configured to use a dynamic port and run start.bat as the entry point.

If we take a look at start.bat, it's pretty simple as well.

set ASPNETCORE_URLS=http://localhost:%Fabric_Endpoint_HelloAspnetSvcTypeEndpoint%
.\hello-aspnetcore.exe

We're setting the ASPNETCORE_URLS variable in the environment before starting the application.

Like the Go app, right-click on the project to publish the app to our local Service Fabric cluster. Once again, use the Service Fabric Explorer to find the port number for this service and open it in a browser.

Deploying more instances of the application

To deploy another version of the ASP.NET Core application, for example, go to the application type node in Service Fabric Explorer and click Create app instance. Enter a unique name and another instance of our application will be created at a different dynamic port, running side-by-side with the first application instance we deployed.

Source code

https://github.com/anthonychu/service-fabric-guest-dynamic-ports