Dajbych.net


Service Fabric Hello World

, 8 minutes to read

Start­ing with a con­sole app is sim­ple. Write a line of text to the con­sole is easy and the re­sult is vis­i­ble im­me­di­ately. Sim­i­lar si­t­u­a­tion is with Uni­ver­sal Win­dows app where is a Text­Block con­trol. Ser­vice Fab­ric is not harder. The most dif­fi­cult part is set­t­ing up your di­ag­nos­tics, be­cause cloud ser­vices does not have any user in­ter­face.

Creating a project

Launch Vi­sual Stu­dio as an Ad­min­is­tra­tor. Open a New Project di­a­log (File → New → Project) and choose Ser­vice Fab­ric Ap­pli­ca­tion (In­stalled → Tem­plates → Vi­sual C# → Cloud). Se­lect State­less Ser­vice. The gen­er­ated project is a hello world ap­pli­ca­tion. When you press F5 (or click to Start) the Di­ag­nos­tics Events win­dows will ap­pear and mes­sages logged by Ser­viceEventSource.Cur­rent.Ser­viceMes­sage method in the loop.

Understanding the entry point

Like the con­sole app has its Main method, ev­ery in­s­tance of Ser­vice Fab­ric app has its Star­tA­sync method. It is lo­cated in the State­less1.cs file in the State­less1 project. The method is called au­to­mat­i­cally af­ter the in­s­tance is started in the same way like the Main method is called after the con­sole app is launched.

The ques­tion is when the method ends. Nat­u­rally it ends when an ex­cep­tion is thrown and is not caught by your code. The con­sole app shuts down, but the Ser­vice Fab­ric in­s­tance is restarted without the in­s­tance be­ing recre­ated. In this case the Ser­vice Fab­ric acts as a watch­dog timer. But there is also an­other indi­ca­tor sig­nal­ing when the method should end. It may hap­pen for ex­am­ple when the un­der­ly­ing op­er­at­ing sys­tem needs to restart af­ter a sys­tem up­date. Two im­ple­men­ta­tion ex­ists. The first one throws an ex­cep­tion:

protected override async Task RunAsync(CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); ... } }

And the sec­ond one ends without re­porting a tran­sient fault:

protected override async Task RunAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { ... } }

Both im­ple­men­ta­tions are cor­rect. The block in­side the while loop con­tains your ser­vice logic.

Event Tracing for Windows

ETW is an ef­fi­cient ker­nel-level trac­ing mech­a­nism. You can con­sume the events in real time or from a log file. It does not slow down the ap­pli­ca­tion, be­cause it drops events when log­ging to a file, the disk is too slow to keep up with the log­ging rate.

Ev­ery event source has its name. It is de­fined in the EventSourceAt­tribute dec­o­rat­ing the Ser­viceEventSource class in the Ser­viceEventSource.cs file. The State­less1 class is reg­is­tered with this class to ETW in the Pro­gram.cs file by call­ing the Ser­vice­TypeReg­is­tered method.

Service Fabric Analytics

OMS (Op­er­a­tions Man­ager Suite) al­lows your or­ga­ni­za­tion to cen­tral­ize mon­i­tor­ing of var­i­ous ser­vices re­gard­less of its kind. It can be also used to mon­i­tor your Ser­vice Fab­ric clus­ter if you set up Azure Di­ag­nos­tics on your Ser­vice Fab­ric VMs and con­fig­ure OMS to col­lect data from your WAD (Win­dows Azure Di­ag­nos­tics) stor­age ta­ble.

Application Insights

An­other op­tion is tak­ing ad­van­tage of AI (Ap­pli­ca­tion In­sights). The con­fig­u­ra­tion was a lit­tle bit eas­ier in the past by ap­ply­ing a sin­gle pack­age, but this ap­proach is dep­re­cated now (most prob­a­bly be­cause it was by­passing ETW).

In or­der to con­nect AI to the ETW source we have to in­clude two projects from GitHub. Projects are not avai­l­able as NuGet pack­ages. You can keep al­ways up-to-date by cloning the source repos­i­tory, but this ap­proach is very de­struc­tive, be­cause you usu­ally need the lat­est sta­ble well tested ver­sion rather than the lat­est bits.

There is an­other choice. You can in­stall the Mi­crosoft.Di­ag­nos­tics.Event­Flow.Ser­vice­Fab­ric NuGet pack­age. It has many de­pen­den­cies and does not sup­port .NET Core in this sce­nario. Af­ter in­stalling the pack­age your project is richer for one file only, which is very pos­i­tive. The file path is Pack­age­Root\Con­fig\event­Flow­Con­fig.json. In this file, you need to un­com­ment the sec­tion with Ap­pli­ca­tion In­sights set­t­ings and paste the in­stru­men­ta­tion key.

{ "outputs": [ { "type": "ApplicationInsights", "instrumentationKey": "00000000-0000-0000-0000-000000000000" } ] }

Next, we need to iden­tify the source of events, which is the value of the Name prop­erty in EventSourceAt­tribute dec­o­rat­ing the Ser­viceEventSource class in the Ser­viceEventSource.cs file.

{ "inputs": [ { "type": "EventSource", "sources": [ { "providerName": "MyCompany-StatelessService-Stateless1" } ] } ] }

Fi­nally, you have to re­place the de­fault en­try point of the ser­vice host pro­cess by di­ag­nos­tic pipe­line.

private static void Main() { try { using (var diagnosticsPipeline = ServiceFabricDiagnosticPipelineFactory.CreatePipeline("MyApplication-MyService-DiagnosticsPipeline")) { ServiceRuntime.RegisterServiceAsync("Stateless1Type", ctx => new Stateless1(ctx)).Wait(); ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(Stateless1).Name); Thread.Sleep(Timeout.Infinite); } } catch (Exception e) { ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString()); throw; } }

Un­for­tu­nately, even run­n­ing this ap­proach lo­cally ends up with ex­cep­tions of var­i­ous kind de­pend­ing on tar­get frame­work (.NET 4.5.2, .NET 4.6.2) and NuGet de­pen­dency be­hav­ior (low­est, high­est).

My workaround

In­stall the Mi­crosoft.Ap­pli­ca­tion­In­sights.Win­dowsServer NuGet pack­age.

Cre­ate an in­s­tance of the Teleme­tryClient class in a sin­gle­ton or in a static class.

using Microsoft.ApplicationInsights; internal sealed class Stateless1 : StatelessService { private readonly TelemetryClient telemetry = new TelemetryClient(); ... }

Mod­ify the Ap­pli­ca­tion­In­sights.con­fig file by in­sert­ing an in­stru­men­ta­tion key into it.

<?xml version="1.0" encoding="utf-8"?> <ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings"> <InstrumentationKey>00000000-0000-0000-0000-000000000000</InstrumentationKey> ... </ApplicationInsights>

Use the Teleme­tryClient as a gate to your Ap­pli­ca­tion In­sights teleme­try.

protected override async Task RunAsync(CancellationToken cancellationToken) { long iterations = 0; while (true) { cancellationToken.ThrowIfCancellationRequested(); telemetry.TrackTrace($"Hello World - {iterations}"); await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); } }

Deploying to Service Fabric Cluster

The first step is a cre­ation of Ser­vice Fab­ric Clus­ter. I rec­om­mend to cre­ate a sep­arate Re­source group for it, be­cause along­side to the clus­ter will be cre­ated many other re­sources – sev­eral stor­age ac­counts, vir­tual ma­chine scale set, vir­tual net­work, load bal­ancer and public IP ad­dress. Fu­ture dele­tion of Ser­vice Fab­ric clus­ter with all its de­pen­den­cies will be much eas­ier.

Ser­vice Fab­ric can be found in Azure por­tal un­der NewCom­pute Ser­vice Fab­ric Clus­ter.

For test­ing pur­poses, I rec­om­mend the fol­low­ing con­fig­u­ra­tion:

When the clus­ter is cre­ated se­lect Pub­lish… from the con­text menu of Ser­vice Fab­ric Ap­pli­ca­tion project. Se­lect the end­point end­ing with clou­dapp.azure.com:19000 and click to Pub­lish.

In the Azure Por­tal on the Ser­vice Fab­ric panel click on…

…and make sure your ap­pli­ca­tion is healthy.

In the Azure Por­tal on the Ap­pli­ca­tion In­sights panel click on…

…and then click on a lit­tle +

…write a sin­gle word…

…and click on…

…then you can see your di­ag­nostics mes­sages from your clus­ter.

When you are done, you can delete your ap­pli­ca­tion from the clus­ter in the Ser­vice Fab­ric Ex­plorer. To do so, se­lect the ap­pli­ca­tion in the left panel and choose the Delete Ap­pli­ca­tion com­mand un­der the Ac­tions but­ton in the right up­per cor­ner.