MahdyTech

Spawning Your First C++ Fleet with Service Fabric and REST SDK

February 04, 2019

I have mostly been working on the details of rather big projects, and that can make one lose touch with end-to-end magic. This week I decided to create a very simple distributed C++ web app, running on an Azure fleet. I settled on using Service Fabric as a distributed framework and CPPREST SDK for building the C++ web server. This is how it went!

Service fabric

Service Fabirc

Service Fabric is an Azure distributed platform solution. It manages orchestration & packaging without the need for containerization. In other words, only binaries are provided to the framework, and it takes care of uploading them to all the machines in the cluster in a safe manner. Running an app on a whole fleet of VMs with several clicks is rather empowering - and Service Fabric allows for that.

Service Fabric is pretty simple to start on and has got good integration with Visual Studio. In my experience though, there are always some knobs that need to be turned before things are working as they are supposed to - more on that later.

Note: Kubernetes is usually what comes to mind when Service Fabric is mentioned, as a very popular orchestrator. However, my experience with containers on windows is pretty bleak, so I went with Service Fabric.

How to Get it

Two main steps are needed to create a Service Fabric app in Visual Studio:

I recommend starting off with Visual Studio, at least to get a look at required config files and standard deployment pipeline. Later on, Visual Studio can be discarded in favor of Configs & PowerShell scripts.

How to Run it

Service Fabric has deep support for .Net and various web technologies, offering stateful services support and more. Nonetheless, C++ devs, don’t despair. It still allows for a Guest Executable project type, where Service Fabric just needs triggering command to run the service, and that’s it.

Service Fabric Project Guest Executable in Service Fabric

Create a Guest Exceutable Service Fabric app in Visual Studio

After creating the project and adding the path to binaries - running the project deploys the app to a local virtual cluster, simulating an actual cluster to a large extent. Make sure to have your Service Fabric Local Cluster manager turned on first.

The cluster manager includes the dashboard, which is pretty cool. It shows the overall metrics of the cluster. For example:

Service Fabric Dashboard

One thing to note is to return -1; in the failure cases. When an app ends with non-zero exit status, Service Fabric understands that the app failed and signals that to the dashboard (or any monitoring setup!).

Let’s move to the cloud

Now that we have got our local app running locally, let’s move where everyone has access! Service Fabric supports on-premise (non-Azure) clusters, but for the sake of getting started, it’s easier to test on Azure. Microsoft has a decent tutorial on how to create the cluster from the Azure Portal, on top I have the following notes:

  • For a first-time test, don’t get the cheapest machine - RDPing into that would be a nightmare. I rather recommend getting a single instance to start with but of decent perf. I got a single DS2_v2 while doing my tests.
  • After primary tests pass, you can cheapen on the model and increase the number of nodes.
  • Pay attention to Status in the portal. It is not articulated but it’s a major indicator of what’s happening. For example, after creating the cluster for the first time, although Azure deployment shows it’s done, the cluster is not actually usable until Status reads Ready.

Status on Service Fabric

Once Service Fabric cluster is ready, any app is publishable from Visual Studio with a couple clicks! Instead of running the project (for local publish), right-click and select Publish. Now, let’s make an app to publish.

Who said C++ is ancient: CPP Rest SDK

C++ is not the easiest language to develop a RESTful web server. However, some tooling sure makes the job easier. CPP Rest SDK is a relatively new library that allows for easy out-of-the-box Server/Client RESTful communication in C++. My experience has been positive and I’d recommend checking it out.

Interlude: vcpkg

For the longest time, consuming packages easily on Windows has been a nightmare. That is until vcpkg came to the scene. VCPkg employs a source-based package management system, incurring a rebuild every time a new library is used. VCPkg has proved itself to be quite essential for Windows users like myself. I cannot really see myself going back to consuming boost the old way - searching for binaries matching my build config, or to keep looking for that blog with the Windows patch.

For REST SDK, after installing VCPkg, I ran the following:

vcpkg install cpprestsdk 

and voila! it’s installed and accessible from any VS project. Lots of ❤️ to vcpkg.

Note: I have recently become aware of conan which is supposed to provide similar functionality. I am yet to try it out for myself tho.

A REST web server

Starting a REST webserver with the sdk is pretty uneventful (as it should!), the following does the trick:

http_listener listener(L"http://*:9009/processrequest");
listener.support(methods::GET, GetHandler);
listener
    .open()
    .then([&listener]() {std::cout<<"\nstarting to listen\n"; })
    .wait();

It does not get much easier than this! I have hosted my source for full implementation. GetHandler in its simplest form should return a status code and a message - for example:

void GetHandlerFunc(const http_request& request)
{
    request.reply(status_codes::OK, "Node ready to serve!");
}

Note that running this listener requires running the app as admin. If the setup is done successfully, GetHandler should run when a request is made to http://127.0.0.1:9009/processrequest.

Putting It Together

Now to the interesting part: running our server on the Service Fabric fleet. After creating a service fabric Guest Executable project and pointing it to our binaries, there remains a couple of things to take care of.

Credentials

As noted above, our app needs Admin Privileges to listen on the associated port (9009 in our case). Service Fabric documentation has a nice explanation of how to set the right permissions fit for your app - I took a shortcut by giving my app admin privileges in ApplicationManifest.xml:

<Principals>
  <Users>
    <User Name="myLocalAccount" AccountType="LocalSystem" />
  </Users>
</Principals>
<Policies>
  <DefaultRunAsPolicy UserRef="myLocalAccount" />
</Policies>

Please don’t use this for production scenarios. It is worth to spend some time getting accurate permissions needed by the app. Unfortunately, Service Fabric is not really making this part easy.

Certificates

Another nice concept is how Service Fabric forces cluster admins and apps to use certificates to run the app on the cloud. That usually entails adding certificate thumbprint to ApplicationManifest.xml:

<Policies>
    ...
    <SecurityAccessPolicies>
      <SecurityAccessPolicy ResourceRef="MyCert" PrincipalRef="myLocalAccount" GrantRights="Full" ResourceType="Certificate" />
    </SecurityAccessPolicies>
  </Policies>
  <Certificates>
    <SecretsCertificate X509FindValue="<Certificate_Thumbprint>" Name="MyCert" />
  </Certificates>

The certificate thumbprint can be found in the portal under Service Fabric Cluster > Security >> Cluster certificates:

Certificate Thumbprint

Without the right settings/credentials, apps won’t be able to run on the remote cluster.

Port Listening Error

This is kind of a side story - and the reason why this project took longer than I had expected. Initially, I had my server running fine on its own (outside Service Fabric), but does not run on Service Fabric, either locally or on Azure. It was returning a 503 Service Unavailable error code, and my breakpoints were never hit. It seemed like requests were not making it to the web server.

After spending some time on many false paths, this article came as a life savior.

The problem had been that I was using this line in Service Fabric to open the port:

<Endpoint Name="HelloSFServiceTypeEndpoint1" Protocol="http" Port="9009"/>

Which, as described in the MSDN blog, causes Service Fabric to listen on those URLs and block the CPP REST SDK from receiving those requests.

I tried to remove the line, but this renders the respective port closed on the cluster nodes. The solution was as simple as changing the protocol from HTTP to TCP, in which Service Fabric seems to open the port, but it does not block the http://*:9009 requests. Final config is available on github.

Final Result

After going through all these hops, it is a pleasure to see the final result! In my case, running http://cpprestsf.eastus2.cloudapp.azure.com:9009/processrequest results in:

final result

No matter how many times I see this, it is still spectacular! The time it takes from editing my code to seeing the request responded to by N machines is <1 minute. Although this is just a test app, the concept is pretty powerful for a test-driven world.

Last Words

Service Fabric & C++ REST SDK got the job done, and it was a lot of fun. C++ is my favorite language. It’d be a shame if I could not spin up a 100% RESTful server whenever I wanted.

I usually work with special-purpose internal tools, so it was new for me getting out there and trying OSS replacements. I hope this article gets even more folks toying with these frameworks! Let me know your favorite non-C++ (sane?) way to spin up a distributed service.



This is Ahmed Mahdy, and these are some of my thoughts, mostly on optimizing performance. Contact me on Twitter