<commit_before>---
layout: post
title: Hosting a web application in Service Fabric
date: '2016-11-01T08:15:00+01:00'
tags: microservices, servicefabric
image: "/blog/assets/article_images/2016-11-01-hosting/andromeda-galaxy.jpg"
image2: "/blog/assets/article_images/2016-11-01-hosting/andromeda-galaxy.jpg"
---

Service Fabric is a platform that is designed to solve the challenges I exposed [in my previous post on Microservices]({{ site.baseurl }}{% post_url 2016-10-26-What-we-dont-tell-you-about-microservices %}). 
It manages a cluster of machines, and lets you work against it as if it was a single host. You send your app to Service Fabric, and the system will host it somewhere, and make it available at a given endpoint.
Of course, that's highly simplified, it does much, much more. It handles things like service discovery, reverse proxy and load balancing, health monitoring, and scaling, stateful services and more...

So, to assess the platform, I look at what it takes to take an existing small web application, and deploy it on a Service Fabric cluster.
It turns out that it is relatively easy.
My application test is a Nancy web app, deployed to IIS. this is a write up of what I had to do.

## Where do we start?

In Service Fabric, you have 2 main choices when it comes to the type of service you can host : Stateful or Stateless.
A Stateless service is simply an endpoint that doesn't have any state attached to it. An API, a Website, or a gateway for example. Stateless service can have a state, but it will be stored externally in a database for example.
A Stateful service can store the data internally, using Reliable Collections provided by Service Fabric. These look just like your usual collections, but Service Fabric makes them highly available and consistent across your services.
For our example I will use a Stateless Service.

So I want to host my Nancy application as a Stateless Service in the cluster. Ideally, I want my service to be unaware of Service Fabric. 
Service Fabric supports [hosting any executable](https://azure.microsoft.com/en-us/documentation/articles/service-fabric-deploy-existing-app/).

## Step 1 : Make the web application self-hosted

We are going ot use OWIN and it's self-host capabilities to achieve this.  
I start by adding the owin packages to my project : 

     "Microsoft.Owin.Host.HttpListener": "3.0.1"
     "Microsoft.Owin.Hosting": "3.0.1"

We add and OWIN Startup configuration class, a Program.cs file with a `static void Main` and set our project to be a Console App. I will get to why I take parameters in :

{% highlight csharp %}
[assembly: OwinStartup(typeof(Web.Startup))]

namespace Web
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseNancy();
        }
    }
}
{% endhighlight %}

{% highlight csharp %}
public class Program
{
   public static void Main(params string[] args)
   {

       int port = 1234;
       string appRoot = "";
       // get port and approot from arguments if provided.
       if (args.Any())
       {
           int.TryParse(args[0], out port);
           appRoot = args[1]?.TrimStart('/') ?? "";
       }

       var url = $"http://+:{port}/{appRoot}";
       using (WebApp.Start(url))
       {
           Console.WriteLine("Listening at " + url);
           Console.ReadLine();
       }
   }
}
{% endhighlight %}

Set the build output to `Console Application` : 
![Console Application](/blog/assets/article_images/2016-11-01-hosting/console.PNG)


When we self-host, [we have to tell our web framework where to find the files](http://stackoverflow.com/questions/24571258/how-do-you-resolve-a-virtual-path-to-a-file-under-an-owin-host) (views, content, etc..).  
With Nancy, we need to configure a RootPathProvider :  
{% highlight csharp %}
public class CustomRootPathProvider : IRootPathProvider
{
     public string GetRootPath()
     {
          return Directory.GetCurrentDirectory();
     }
}

public class Bootstrapper : DefaultNancyBootstrapper
{
    protected override IRootPathProvider RootPathProvider {
        get { return new CustomRootPathProvider(); }
    }
    ...
}
{% endhighlight %}

That's it, the app is now self-hosted. you can start it as a console app by running F5 and open your browser at `http://localhost:1234`.

The next step is to host this executable in ServiceFabric.

## Step 2 : Guest Executable in Service Fabric

For this, the Service Fabric SDK with VS tooling needs to be installed. the easiest way is by using the [Web Platform Installer](https://www.microsoft.com/en-us/download/details.aspx?id=6164)

I like to keep my code agnostic of the infrastructure. This is why I choose the guest executable. 
If you have the SDK installed, you can do Add New Project, search for Service Fabric, and add a Guest Exectuable Service Fabric project to your solution.
This will keep the xml files that describe your executable (ServiceManifext.xml) within the service fabric project, instead of having to mix them in your web project. Note that the Service Fabric project is basically a set of XML files, a link to the binaries of your app, and a powershell script to deploy it to the cluster. So with some work, you could make this an infrastructure concern, and not even add this project to the solution.
Anyway, the procedure is well described here : [Deploy a guest executable to Service Fabric](https://azure.microsoft.com/en-us/documentation/articles/service-fabric-deploy-existing-app/)  

I will focus on the tweaks I made to get it all work nicely.

1. Set your project's Platform Target x64 (Project Properties > Build > Platform Target). Service Fabric supports only x64.  

2. Choose link for the Code Package Behaviour on project creation (it's the default).  
In my case, linking did not work recursively. So I edited the SF csproj according to [this Stackoverflow answer](http://stackoverflow.com/a/11808911/156415) :

          <Content Include="..\Web\bin\**\*.*"> 
               <Link>ApplicationPackageRoot\ElectronicConsentPkg\Code\%(RecursiveDir)%(FileName)%(Extension)</Link>
          </Content>  

This will ensure that subfolders are also included (i.e: content, js, views, etc..).  

3. ApplicationManifest  
An application in Service fabric can be composed of multiple services and endpoints. It is your deployment unit.
The ApplicationTypeName value is important as it defines the id of your application (and of your service) in Service Fabric service discovery system. It also ends up being part of the url to your service. More on that below.  <commit_msg>ol numbering...<commit_after>---
layout: post
title: Hosting a web application in Service Fabric
date: '2016-11-01T08:15:00+01:00'
tags: microservices, servicefabric
image: "/blog/assets/article_images/2016-11-01-hosting/andromeda-galaxy.jpg"
image2: "/blog/assets/article_images/2016-11-01-hosting/andromeda-galaxy.jpg"
---

Service Fabric is a platform that is designed to solve the challenges I exposed [in my previous post on Microservices]({{ site.baseurl }}{% post_url 2016-10-26-What-we-dont-tell-you-about-microservices %}). 
It manages a cluster of machines, and lets you work against it as if it was a single host. You send your app to Service Fabric, and the system will host it somewhere, and make it available at a given endpoint.
Of course, that's highly simplified, it does much, much more. It handles things like service discovery, reverse proxy and load balancing, health monitoring, and scaling, stateful services and more...

So, to assess the platform, I look at what it takes to take an existing small web application, and deploy it on a Service Fabric cluster.
It turns out that it is relatively easy.
My application test is a Nancy web app, deployed to IIS. this is a write up of what I had to do.

## Where do we start?

In Service Fabric, you have 2 main choices when it comes to the type of service you can host : Stateful or Stateless.
A Stateless service is simply an endpoint that doesn't have any state attached to it. An API, a Website, or a gateway for example. Stateless service can have a state, but it will be stored externally in a database for example.
A Stateful service can store the data internally, using Reliable Collections provided by Service Fabric. These look just like your usual collections, but Service Fabric makes them highly available and consistent across your services.
For our example I will use a Stateless Service.

So I want to host my Nancy application as a Stateless Service in the cluster. Ideally, I want my service to be unaware of Service Fabric. 
Service Fabric supports [hosting any executable](https://azure.microsoft.com/en-us/documentation/articles/service-fabric-deploy-existing-app/).

## Step 1 : Make the web application self-hosted

We are going ot use OWIN and it's self-host capabilities to achieve this.  
I start by adding the owin packages to my project : 

     "Microsoft.Owin.Host.HttpListener": "3.0.1"
     "Microsoft.Owin.Hosting": "3.0.1"

We add and OWIN Startup configuration class, a Program.cs file with a `static void Main` and set our project to be a Console App. I will get to why I take parameters in :

{% highlight csharp %}
[assembly: OwinStartup(typeof(Web.Startup))]

namespace Web
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseNancy();
        }
    }
}
{% endhighlight %}

{% highlight csharp %}
public class Program
{
   public static void Main(params string[] args)
   {

       int port = 1234;
       string appRoot = "";
       // get port and approot from arguments if provided.
       if (args.Any())
       {
           int.TryParse(args[0], out port);
           appRoot = args[1]?.TrimStart('/') ?? "";
       }

       var url = $"http://+:{port}/{appRoot}";
       using (WebApp.Start(url))
       {
           Console.WriteLine("Listening at " + url);
           Console.ReadLine();
       }
   }
}
{% endhighlight %}

Set the build output to `Console Application` : 
![Console Application](/blog/assets/article_images/2016-11-01-hosting/console.PNG)


When we self-host, [we have to tell our web framework where to find the files](http://stackoverflow.com/questions/24571258/how-do-you-resolve-a-virtual-path-to-a-file-under-an-owin-host) (views, content, etc..).  
With Nancy, we need to configure a RootPathProvider :  
{% highlight csharp %}
public class CustomRootPathProvider : IRootPathProvider
{
     public string GetRootPath()
     {
          return Directory.GetCurrentDirectory();
     }
}

public class Bootstrapper : DefaultNancyBootstrapper
{
    protected override IRootPathProvider RootPathProvider {
        get { return new CustomRootPathProvider(); }
    }
    ...
}
{% endhighlight %}

That's it, the app is now self-hosted. you can start it as a console app by running F5 and open your browser at `http://localhost:1234`.

The next step is to host this executable in ServiceFabric.

## Step 2 : Guest Executable in Service Fabric

For this, the Service Fabric SDK with VS tooling needs to be installed. the easiest way is by using the [Web Platform Installer](https://www.microsoft.com/en-us/download/details.aspx?id=6164)

I like to keep my code agnostic of the infrastructure. This is why I choose the guest executable. 
If you have the SDK installed, you can do Add New Project, search for Service Fabric, and add a Guest Exectuable Service Fabric project to your solution.
This will keep the xml files that describe your executable (ServiceManifext.xml) within the service fabric project, instead of having to mix them in your web project. Note that the Service Fabric project is basically a set of XML files, a link to the binaries of your app, and a powershell script to deploy it to the cluster. So with some work, you could make this an infrastructure concern, and not even add this project to the solution.
Anyway, the procedure is well described here : [Deploy a guest executable to Service Fabric](https://azure.microsoft.com/en-us/documentation/articles/service-fabric-deploy-existing-app/)  

I will focus on the tweaks I made to get it all work nicely.

1. Set your project's Platform Target x64 (Project Properties > Build > Platform Target). Service Fabric supports only x64.  

2. Choose link for the Code Package Behaviour on project creation (it's the default).  
In my case, linking did not work recursively. So I edited the SF csproj according to [this Stackoverflow answer](http://stackoverflow.com/a/11808911/156415). This will ensure that subfolders are also included (i.e: content, js, views, etc..). :  

          <Content Include="..\Web\bin\**\*.*"> 
               <Link>ApplicationPackageRoot\ElectronicConsentPkg\Code\%(RecursiveDir)%(FileName)%(Extension)</Link>
          </Content>

3. ApplicationManifest  
An application in Service fabric can be composed of multiple services and endpoints. It is your deployment unit.
The ApplicationTypeName value is important as it defines the id of your application (and of your service) in Service Fabric service discovery system. It also ends up being part of the url to your service. More on that below.  
{'fraction_non_alphanumeric': 0.07956270877619193, 'fraction_numerical': 0.01579107197084725, 'mean_word_length': 3.620484040687478, 'pattern_counts': {'":': 4, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 6, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3955601', 'n_tokens_mistral': 3767, 'n_tokens_neox': 3490, 'n_words': 1667}