Udostępnij za pośrednictwem


Samouczek: tworzenie aplikacji usługi Service Fabric platformy .NET

Ten samouczek jest częścią jednej z serii. Z tego samouczka dowiesz się, jak utworzyć aplikację usługi Azure Service Fabric z frontonem internetowego interfejsu API platformy ASP.NET Core i stanową usługą zaplecza do przechowywania danych. Po zakończeniu masz aplikację do głosowania z frontonem internetowym ASP.NET Core, która zapisuje wyniki głosowania w stanowej usłudze zaplecza w klastrze.

Ta seria samouczków wymaga komputera dewelopera z systemem Windows. Jeśli nie chcesz ręcznie tworzyć aplikacji do głosowania, możesz pobrać kod źródłowy ukończonej aplikacji i przejść od razu do sekcji Szczegółowe omówienie przykładowej aplikacji do głosowania. Możesz również wyświetlić przewodnik wideo z tego samouczka.

Diagram przedstawiający fronton interfejsu API Platformy ASP.NET i platformy AngularJS łączący się z stanową usługą zaplecza w usłudze Service Fabric.

Z tego samouczka dowiesz się, jak wykonywać następujące czynności:

  • Tworzenie usługi internetowego interfejsu API platformy ASP.NET Core jako niezawodnej stanowej usługi
  • Tworzenie usługi aplikacji internetowej platformy ASP.NET Core jako bezstanowej usługi internetowej
  • Używanie zwrotnego serwera proxy do komunikowania się z usługą stanową

W serii samouczków pokazano, jak wykonać następujące działania:

Wymagania wstępne

Przed rozpoczęciem tego samouczka:

Tworzenie usługi internetowego interfejsu API platformy ASP.NET jako niezawodnej usługi

Najpierw utwórz fronton internetowy aplikacji do głosowania przy użyciu ASP.NET Core. ASP.NET Core to uproszczone międzyplatformowe środowisko programistyczne, którego można używać do tworzenia nowoczesnych internetowych interfejsów użytkownika i interfejsów API.

Aby uzyskać pełną wiedzę na temat integracji ASP.NET Core z usługą Service Fabric, zdecydowanie zalecamy przejrzenie ASP.NET Core w usłudze Service Fabric Reliable Services. Na tym etapie wystarczy wykonać czynności opisane w tym samouczku, aby szybko rozpocząć pracę. Aby dowiedzieć się więcej na temat ASP.NET Core, zobacz dokumentację platformy ASP.NET Core.

Aby utworzyć usługę:

  1. Otwórz program Visual Studio przy użyciu opcji Uruchom jako administrator .

  2. Wybierz pozycję Plik>nowy>projekt, aby utworzyć nowy projekt.

  3. W obszarze Tworzenie nowego projektu wybierz pozycję Aplikacja usługi Cloud>Service Fabric. Wybierz Dalej.

    Zrzut ekranu przedstawiający okno dialogowe Tworzenie nowego projektu w programie Visual Studio.

  4. Wybierz pozycję Bezstanowe ASP.NET Core dla nowego typu projektu, nadaj usłudze nazwę VotingWeb, a następnie wybierz pozycję Utwórz.

    Zrzut ekranu przedstawiający wybieranie usługi internetowej ASP.NET w nowym okienku usługi.

  5. W następnym okienku zostanie wyświetlony zestaw szablonów projektów ASP.NET Core. Na potrzeby tego samouczka wybierz pozycję Aplikacja internetowa (Model-View-Controller), a następnie wybierz przycisk OK.

    Zrzut ekranu przedstawiający wybieranie typu projektu ASP.NET.

    Program Visual Studio tworzy aplikację i projekt usługi, a następnie wyświetla je w programie Visual Studio Eksplorator rozwiązań:

    Zrzut ekranu przedstawiający Eksplorator rozwiązań po utworzeniu aplikacji przy użyciu podstawowej usługi internetowego interfejsu API ASP.NET.

Aktualizowanie pliku site.js

Przejdź do strony wwwroot/js/site.js i otwórz plik. Zastąp zawartość pliku następującym kodem JavaScript używanym przez widoki Narzędzia główne, a następnie zapisz zmiany.

var app = angular.module('VotingApp', ['ui.bootstrap']);
app.run(function () { });

app.controller('VotingAppController', ['$rootScope', '$scope', '$http', '$timeout', function ($rootScope, $scope, $http, $timeout) {

    $scope.refresh = function () {
        $http.get('api/Votes?c=' + new Date().getTime())
            .then(function (data, status) {
                $scope.votes = data;
            }, function (data, status) {
                $scope.votes = undefined;
            });
    };

    $scope.remove = function (item) {
        $http.delete('api/Votes/' + item)
            .then(function (data, status) {
                $scope.refresh();
            })
    };

    $scope.add = function (item) {
        var fd = new FormData();
        fd.append('item', item);
        $http.put('api/Votes/' + item, fd, {
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
        })
            .then(function (data, status) {
                $scope.refresh();
                $scope.item = undefined;
            })
    };
}]);

Aktualizowanie pliku Index.cshtml

Przejdź do pozycji Views/Home/Index.cshtml i otwórz plik. Ten plik ma widok specyficzny dla kontrolera home. Zastąp jego zawartość następującym kodem, a następnie zapisz zmiany.

@{
    ViewData["Title"] = "Service Fabric Voting Sample";
}

<div ng-controller="VotingAppController" ng-init="refresh()">
    <div class="container-fluid">
        <div class="row">
            <div class="col-xs-8 col-xs-offset-2 text-center">
                <h2>Service Fabric Voting Sample</h2>
            </div>
        </div>

        <div class="row">
            <div class="col-xs-8 col-xs-offset-2">
                <form class="col-xs-12 center-block">
                    <div class="col-xs-6 form-group">
                        <input id="txtAdd" type="text" class="form-control" placeholder="Add voting option" ng-model="item"/>
                    </div>
                    <button id="btnAdd" class="btn btn-default" ng-click="add(item)">
                        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                        Add
                    </button>
                </form>
            </div>
        </div>

        <hr/>

        <div class="row">
            <div class="col-xs-8 col-xs-offset-2">
                <div class="row">
                    <div class="col-xs-4">
                        Click to vote
                    </div>
                </div>
                <div class="row top-buffer" ng-repeat="vote in votes.data">
                    <div class="col-xs-8">
                        <button class="btn btn-success text-left btn-block" ng-click="add(vote.Key)">
                            <span class="pull-left">
                                {{vote.key}}
                            </span>
                            <span class="badge pull-right">
                                {{vote.value}} Votes
                            </span>
                        </button>
                    </div>
                    <div class="col-xs-4">
                        <button class="btn btn-danger pull-right btn-block" ng-click="remove(vote.Key)">
                            <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
                            Remove
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Aktualizowanie pliku _Layout.cshtml

Przejdź do pozycji Views/Shared/_Layout.cshtml i otwórz plik. Ten plik ma domyślny układ aplikacji ASP.NET. Zastąp jego zawartość następującym kodem, a następnie zapisz zmiany.

<!DOCTYPE html>
<html ng-app="VotingApp" xmlns:ng="https://angularjs.org">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>@ViewData["Title"]</title>

    <link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet"/>
    <link href="~/css/site.css" rel="stylesheet"/>

</head>
<body>
<div class="container body-content">
    @RenderBody()
</div>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.js"></script>
<script src="~/js/site.js"></script>

@RenderSection("Scripts", required: false)
</body>
</html>

Aktualizowanie pliku VotingWeb.cs

Otwórz plik VotingWeb.cs. Ten plik tworzy ASP.NET Core WebHost wewnątrz usługi bezstanowej przy użyciu serwera internetowego WebListener.

Na początku pliku dodaj dyrektywę using System.Net.Http; .

CreateServiceInstanceListeners() Zastąp funkcję następującym kodem, a następnie zapisz zmiany.

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(
            serviceContext =>
                new KestrelCommunicationListener(
                    serviceContext,
                    "ServiceEndpoint",
                    (url, listener) =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                        return new WebHostBuilder()
                            .UseKestrel()
                            .ConfigureServices(
                                services => services
                                    .AddSingleton<HttpClient>(new HttpClient())
                                    .AddSingleton<FabricClient>(new FabricClient())
                                    .AddSingleton<StatelessServiceContext>(serviceContext))
                            .UseContentRoot(Directory.GetCurrentDirectory())
                            .UseStartup<Startup>()
                            .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                            .UseUrls(url)
                            .Build();
                    }))
    };
}

Następnie dodaj następującą GetVotingDataServiceName metodę po CreateServiceInstanceListeners()metodzie , a następnie zapisz zmiany. Metoda GetVotingDataServiceName zwraca nazwę usługi w przypadku sondowania.

internal static Uri GetVotingDataServiceName(ServiceContext context)
{
    return new Uri($"{context.CodePackageActivationContext.ApplicationName}/VotingData");
}

Dodawanie pliku VotesController.cs

Dodaj kontroler w celu zdefiniowania akcji głosowania. Kliknij prawym przyciskiem myszy folder Controllers, a następnie wybierz polecenie Dodaj>nowy element>Visual C#>ASP.NET Core>Class. Nadaj plikowi nazwę VotesController.cs, a następnie wybierz pozycję Dodaj.

Zastąp zawartość pliku VotesController.cs następującym kodem, a następnie zapisz zmiany. Dalej, w sekcji Aktualizowanie pliku VotesController.cs, ten plik zostanie zmodyfikowany na potrzeby odczytywania danych głosowania z usługi zaplecza i ich zapisywania. Na razie ten kontroler zwraca do widoku dane w postaci statycznego ciągu.

namespace VotingWeb.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Fabric;
    using System.Fabric.Query;
    using System.Linq;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Newtonsoft.Json;

    [Produces("application/json")]
    [Route("api/Votes")]
    public class VotesController : Controller
    {
        private readonly HttpClient httpClient;

        public VotesController(HttpClient httpClient)
        {
            this.httpClient = httpClient;
        }

        // GET: api/Votes
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            List<KeyValuePair<string, int>> votes= new List<KeyValuePair<string, int>>();
            votes.Add(new KeyValuePair<string, int>("Pizza", 3));
            votes.Add(new KeyValuePair<string, int>("Ice cream", 4));

            return Json(votes);
        }
     }
}

Konfigurowanie portu nasłuchującego

Po utworzeniu usługi frontonu VotingWeb program Visual Studio losowo wybiera port, na którym usługa będzie nasłuchiwała. Usługa VotingWeb działa jako fronton dla tej aplikacji i akceptuje ruch zewnętrzny. W tej sekcji powiążesz tę usługę ze stałym i dobrze znanym portem. Manifest usługi deklaruje punkty końcowe usługi.

W Eksploratorze rozwiązań otwórz plik VotingWeb/PackageRoot/ServiceManifest.xml. Resources W sekcji znajdź Endpoint element , a następnie zmień wartość na Port 8080.

Aby wdrożyć i uruchomić aplikację lokalnie, port nasłuchujący aplikacji musi być otwarty i dostępny na komputerze.

<Resources>
    <Endpoints>
      <!-- This endpoint is used by the communication listener to obtain the port on which to 
           listen. Please note that if your service is partitioned, this port is shared with 
           replicas of different partitions that are placed in your code. -->
      <Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="8080" />
    </Endpoints>
  </Resources>

Następnie zaktualizuj Application URL wartość właściwości w projekcie Voting, aby przeglądarka internetowa otwierała prawidłowy port podczas debugowania aplikacji. W Eksplorator rozwiązań wybierz projekt Voting, a następnie zaktualizuj Application URL właściwość na 8080.

Wdrażanie i uruchamianie aplikacji Voting lokalnie

Teraz możesz uruchomić aplikację Voting, aby ją debugować. W programie Visual Studio wybierz pozycję F5, aby wdrożyć aplikację w lokalnym klastrze usługi Service Fabric w trybie debugowania. Aplikacja kończy się niepowodzeniem, jeśli wcześniej nie otwarto programu Visual Studio przy użyciu opcji Uruchom jako administrator .

Uwaga

Przy pierwszym uruchomieniu i wdrożeniu aplikacji lokalnie program Visual Studio tworzy lokalny klaster usługi Service Fabric do użycia do debugowania. Proces tworzenia klastra może zająć trochę czasu. Stan tworzenia klastra jest wyświetlany w oknie Dane wyjściowe programu Visual Studio.

Po wdrożeniu aplikacji do głosowania w lokalnym klastrze usługi Service Fabric aplikacja internetowa zostanie automatycznie otwarta na karcie przeglądarki. Wygląda podobnie do tego przykładu:

Zrzut ekranu przedstawiający fronton aplikacji w przeglądarce.

Aby zatrzymać debugowanie aplikacji, wróć do programu Visual Studio i wybierz pozycję Shift+F5.

Dodawanie stanowej usługi zaplecza do aplikacji

Teraz, gdy usługa internetowego interfejsu API ASP.NET jest uruchomiona w aplikacji, dodaj stanową niezawodną usługę do przechowywania niektórych danych w aplikacji.

Za pomocą usługi Service Fabric można spójnie i niezawodnie przechowywać dane w usłudze przy użyciu niezawodnych kolekcji. Niezawodne kolekcje to zestaw klas kolekcji o wysokiej dostępności i niezawodności, które są znane każdemu, kto ma doświadczenie w korzystaniu z kolekcji języka C#.

Aby utworzyć usługę, która przechowuje wartość licznika w niezawodnej kolekcji:

  1. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy pozycję Usługi w projekcie aplikacji do głosowania i wybierz pozycję Dodaj>nową usługę Service Fabric.

  2. W oknie dialogowym Nowa usługa Service Fabric wybierz pozycję Stanowe ASP.NET Core, nadaj usłudze nazwę VotingData, a następnie wybierz przycisk OK.

    Po utworzeniu projektu usługi masz dwie usługi w aplikacji. W miarę kontynuowania tworzenia aplikacji możesz dodać więcej usług w taki sam sposób. Każda usługa może być niezależnie wersjonowana i uaktualniana.

  3. W następnym okienku zostanie wyświetlony zestaw szablonów projektów ASP.NET Core. Na potrzeby tego samouczka wybierz pozycję Interfejs API.

    Program Visual Studio tworzy projekt usługi VotingData i wyświetla go w Eksplorator rozwiązań:

    Zrzut ekranu przedstawiający projekt usługi VotingData w Eksplorator rozwiązań.

Dodawanie pliku VoteDataController.cs

W projekcie VotingData kliknij prawym przyciskiem myszy folder Controllers, a następnie wybierz polecenie Dodaj>nową klasę elementu.> Nadaj plikowi nazwę VoteDataController.cs i wybierz pozycję Dodaj. Zastąp zawartość pliku następującym kodem, a następnie zapisz zmiany.

namespace VotingData.Controllers
{
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.ServiceFabric.Data;
    using Microsoft.ServiceFabric.Data.Collections;

    [Route("api/[controller]")]
    public class VoteDataController : Controller
    {
        private readonly IReliableStateManager stateManager;

        public VoteDataController(IReliableStateManager stateManager)
        {
            this.stateManager = stateManager;
        }

        // GET api/VoteData
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            CancellationToken ct = new CancellationToken();

            IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

            using (ITransaction tx = this.stateManager.CreateTransaction())
            {
                Microsoft.ServiceFabric.Data.IAsyncEnumerable<KeyValuePair<string, int>> list = await votesDictionary.CreateEnumerableAsync(tx);

                Microsoft.ServiceFabric.Data.IAsyncEnumerator<KeyValuePair<string, int>> enumerator = list.GetAsyncEnumerator();

                List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();

                while (await enumerator.MoveNextAsync(ct))
                {
                    result.Add(enumerator.Current);
                }

                return this.Json(result);
            }
        }

        // PUT api/VoteData/name
        [HttpPut("{name}")]
        public async Task<IActionResult> Put(string name)
        {
            IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

            using (ITransaction tx = this.stateManager.CreateTransaction())
            {
                await votesDictionary.AddOrUpdateAsync(tx, name, 1, (key, oldvalue) => oldvalue + 1);
                await tx.CommitAsync();
            }

            return new OkResult();
        }

        // DELETE api/VoteData/name
        [HttpDelete("{name}")]
        public async Task<IActionResult> Delete(string name)
        {
            IReliableDictionary<string, int> votesDictionary = await this.stateManager.GetOrAddAsync<IReliableDictionary<string, int>>("counts");

            using (ITransaction tx = this.stateManager.CreateTransaction())
            {
                if (await votesDictionary.ContainsKeyAsync(tx, name))
                {
                    await votesDictionary.TryRemoveAsync(tx, name);
                    await tx.CommitAsync();
                    return new OkResult();
                }
                else
                {
                    return new NotFoundResult();
                }
            }
        }
    }
}

Łączenie usług

W tej sekcji połączysz dwie usługi. Aplikacja internetowa frontonu uzyskuje informacje o głosowaniu z usługi zaplecza, a następnie ustawia informacje w aplikacji.

Usługa Service Fabric zapewnia pełną elastyczność w sposobie komunikowania się z niezawodnymi usługami. W ramach jednej aplikacji mogą istnieć usługi, które są dostępne za pośrednictwem protokołu TCP/IP, za pośrednictwem interfejsu API REST PROTOKOŁU HTTP lub za pośrednictwem protokołu WebSocket. Aby zapoznać się z dostępnymi opcjami i ich kompromisami, zobacz Komunikacja z usługami.

W tym samouczku użyto ASP.NET Core internetowego interfejsu API i zwrotnego serwera proxy usługi Service Fabric, aby usługa internetowa frontonu VotingWeb mogła komunikować się z usługą VotingData zaplecza. Zwrotny serwer proxy jest domyślnie skonfigurowany do używania portu 19081. Port zwrotnego serwera proxy jest ustawiany w szablonie usługi Azure Resource Manager, który konfiguruje klaster. Aby dowiedzieć się, który port jest używany, poszukaj w szablonie klastra w zasobie Microsoft.ServiceFabric/clusters :

"nodeTypes": [
          {
            ...
            "httpGatewayEndpointPort": "[variables('nt0fabricHttpGatewayPort')]",
            "isPrimary": true,
            "vmInstanceCount": "[parameters('nt0InstanceCount')]",
            "reverseProxyEndpointPort": "[parameters('SFReverseProxyPort')]"
          }
        ],

Aby znaleźć port zwrotnego serwera proxy używany w lokalnym klastrze programistycznym, wyświetl HttpApplicationGatewayEndpoint element w lokalnym manifeście klastra usługi Service Fabric:

  1. Aby otworzyć narzędzie Service Fabric Explorer, otwórz przeglądarkę i przejdź do http://localhost:19080witryny .
  2. Wybierz pozycję Manifest klastra>.
  3. Zanotuj HttpApplicationGatewayEndpoint port elementu. Domyślnie port to 19081. Jeśli nie jest to 19081, zmień port w GetProxyAddress metodzie VotesController.cs kodu zgodnie z opisem w następnej sekcji.

Aktualizowanie pliku VotesController.cs

W projekcie VotingWeb otwórz plik Controllers/VotesController.cs . Zastąp VotesController zawartość definicji klasy następującym kodem, a następnie zapisz zmiany. Jeśli port zwrotnego serwera proxy wykryty w kroku nie jest 19081, zmień port w GetProxyAddress metodzie z 19081 na odnaleziony port.

public class VotesController : Controller
{
    private readonly HttpClient httpClient;
    private readonly FabricClient fabricClient;
    private readonly StatelessServiceContext serviceContext;

    public VotesController(HttpClient httpClient, StatelessServiceContext context, FabricClient fabricClient)
    {
        this.fabricClient = fabricClient;
        this.httpClient = httpClient;
        this.serviceContext = context;
    }

    // GET: api/Votes
    [HttpGet("")]
    public async Task<IActionResult> Get()
    {
        Uri serviceName = VotingWeb.GetVotingDataServiceName(this.serviceContext);
        Uri proxyAddress = this.GetProxyAddress(serviceName);

        ServicePartitionList partitions = await this.fabricClient.QueryManager.GetPartitionListAsync(serviceName);

        List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();

        foreach (Partition partition in partitions)
        {
            string proxyUrl =
                $"{proxyAddress}/api/VoteData?PartitionKey={((Int64RangePartitionInformation) partition.PartitionInformation).LowKey}&PartitionKind=Int64Range";

            using (HttpResponseMessage response = await this.httpClient.GetAsync(proxyUrl))
            {
                if (response.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    continue;
                }

                result.AddRange(JsonConvert.DeserializeObject<List<KeyValuePair<string, int>>>(await response.Content.ReadAsStringAsync()));
            }
        }

        return this.Json(result);
    }

    // PUT: api/Votes/name
    [HttpPut("{name}")]
    public async Task<IActionResult> Put(string name)
    {
        Uri serviceName = VotingWeb.GetVotingDataServiceName(this.serviceContext);
        Uri proxyAddress = this.GetProxyAddress(serviceName);
        long partitionKey = this.GetPartitionKey(name);
        string proxyUrl = $"{proxyAddress}/api/VoteData/{name}?PartitionKey={partitionKey}&PartitionKind=Int64Range";

        StringContent putContent = new StringContent($"{{ 'name' : '{name}' }}", Encoding.UTF8, "application/json");
        putContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

        using (HttpResponseMessage response = await this.httpClient.PutAsync(proxyUrl, putContent))
        {
            return new ContentResult()
            {
                StatusCode = (int) response.StatusCode,
                Content = await response.Content.ReadAsStringAsync()
            };
        }
    }

    // DELETE: api/Votes/name
    [HttpDelete("{name}")]
    public async Task<IActionResult> Delete(string name)
    {
        Uri serviceName = VotingWeb.GetVotingDataServiceName(this.serviceContext);
        Uri proxyAddress = this.GetProxyAddress(serviceName);
        long partitionKey = this.GetPartitionKey(name);
        string proxyUrl = $"{proxyAddress}/api/VoteData/{name}?PartitionKey={partitionKey}&PartitionKind=Int64Range";

        using (HttpResponseMessage response = await this.httpClient.DeleteAsync(proxyUrl))
        {
            if (response.StatusCode != System.Net.HttpStatusCode.OK)
            {
                return this.StatusCode((int) response.StatusCode);
            }
        }

        return new OkResult();
    }


    /// <summary>
    /// Constructs a reverse proxy URL for a given service.
    /// Example: http://localhost:19081/VotingApplication/VotingData/
    /// </summary>
    /// <param name="serviceName"></param>
    /// <returns></returns>
    private Uri GetProxyAddress(Uri serviceName)
    {
        return new Uri($"http://localhost:19081{serviceName.AbsolutePath}");
    }

    /// <summary>
    /// Creates a partition key from the given name.
    /// Uses the zero-based numeric position in the alphabet of the first letter of the name (0-25).
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    private long GetPartitionKey(string name)
    {
        return Char.ToUpper(name.First()) - 'A';
    }
}

Szczegółowe omówienie przykładowej aplikacji do głosowania

Aplikacja do głosowania składa się z dwóch usług:

  • Usługa frontonu internetowego (VotingWeb): usługa frontonu internetowego platformy ASP.NET Core, która obsługuje stronę internetową i uwidacznia internetowe interfejsy API do komunikowania się z usługą zaplecza.
  • Usługa zaplecza (VotingData): usługa internetowa platformy ASP.NET Core, która uwidacznia interfejs API do przechowywania wyników głosowania w niezawodnym słowniku utrwalonego na dysku.

Diagram przedstawiający usługi aplikacji.

Podczas głosowania w aplikacji występują następujące zdarzenia:

  1. Plik JavaScript wysyła żądanie głosowania do internetowego interfejsu API w usłudze frontonu internetowego jako żądanie HTTP PUT.

  2. Usługa internetowa frontonu używa serwera proxy w celu zlokalizowania i przesłania żądania HTTP PUT do usługi zaplecza.

  3. Usługa zaplecza pobiera żądanie przychodzące i przechowuje zaktualizowany wynik w niezawodnym słowniku. Słownik jest replikowany do wielu węzłów w klastrze i utrwalany na dysku. Wszystkie dane aplikacji są przechowywane w klastrze, więc baza danych nie jest wymagana.

Debugowanie w programie Visual Studio

Podczas debugowania aplikacji w programie Visual Studio należy użyć lokalnego klastra programistycznego usługi Service Fabric. Możesz dostosować środowisko debugowania do swojego scenariusza.

W tej aplikacji przechowuj dane w usłudze zaplecza przy użyciu niezawodnego słownika. Program Visual Studio domyślnie usuwa aplikację po zatrzymaniu debugera. Usunięcie aplikacji spowoduje, że dane w usłudze zaplecza także zostaną usunięte. Aby zachować dane między sesjami debugowania, możesz zmienić Tryb debugowania aplikacji jako właściwość w projekcie Voting (Głosowanie) w programie Visual Studio.

Aby zobaczyć, co się dzieje w kodzie, wykonaj następujące kroki:

  1. Otwórz plik VotingWeb\VotesController.cs i ustaw punkt przerwania w metodzie internetowego interfejsu Put API (wiersz 72).

  2. Otwórz plik VotingData\VoteDataController.cs i ustaw punkt przerwania w metodzie tego internetowego interfejsu Put API (wiersz 54).

  3. Wybierz klawisz F5, aby uruchomić aplikację w trybie debugowania.

  4. Wróć do przeglądarki i wybierz opcję głosowania lub dodaj nową opcję głosowania. Pierwszy punkt przerwania został osiągnięty w kontrolerze interfejsu API frontonu internetowego.

    Skrypt JavaScript w przeglądarce wysyła żądanie do internetowego kontrolera interfejsu API w usłudze frontonu:

    Zrzut ekranu przedstawiający dodawanie usługi frontonu głosowania.

    1. Najpierw skonstruuj adres URL odwrotnego serwera proxy dla usługi zaplecza. (1)
    2. Następnie wyślij żądanie HTTP PUT do zwrotnego serwera proxy. (2)
    3. Na koniec zwróć odpowiedź z usługi zaplecza do klienta. (3)
  5. Wybierz klawisz F5, aby kontynuować.

    Teraz znajdujesz się w punkcie przerwania w usłudze zaplecza:

    Zrzut ekranu przedstawiający dodawanie głosu do usługi zaplecza.

    1. W pierwszym wierszu metody użyj polecenia stateManager , aby pobrać lub dodać niezawodny słownik o nazwie counts. (1)
    2. Wszystkie interakcje, które mają wartości w niezawodnym słowniku, wymagają transakcji. Ta using instrukcja tworzy tę transakcję. (2)
    3. W transakcji zaktualizuj wartość odpowiedniego klucza dla opcji głosowania i zatwierdź operację. commit Gdy metoda zwraca, dane są aktualizowane w słowniku. Następnie jest replikowany do innych węzłów w klastrze. Dane są teraz bezpiecznie przechowywane w klastrze, a usługa zaplecza może przejść w tryb failover do innych węzłów i nadal mieć dostępne dane. (3)
  6. Wybierz klawisz F5, aby kontynuować.

Aby zatrzymać sesję debugowania, wybierz pozycję Shift+F5.

Następny krok

Przejdź do następnego samouczka: