Share via


Oktatóanyag: Alkalmazás létrehozása és üzembe helyezése egy ASP.NET Core Web API kezelőfelületi szolgáltatás és egy állapotalapú háttérszolgáltatás segítségével

Ez az oktatóanyag egy sorozat első része. Megtudhatja, hogyan hozhat létre egy Azure Service Fabric-alkalmazást egy ASP.NET Core Web API kezelőfelületi és egy állapotalapú háttérszolgáltatás segítségével az adatok tárolásához. Az útmutató elvégzése után rendelkezni fog egy ASP.NET Core webes kezelőfelületes szavazóalkalmazással, amely egy, a fürtben található állapotalapú háttérszolgáltatásba menti a szavazati adatokat. Ez az oktatóanyag-sorozat windowsos fejlesztői gépet igényel. Ha nem szeretné manuálisan létrehozni a szavazóalkalmazást, akkor letöltheti a forráskódot a kész alkalmazáshoz, és folytathatja a mintául szolgáló szavazóalkalmazás bemutatásával. Ha szeretné, megtekintheti az oktatóanyag útmutató videóját.

AngularJS+ASP.NET API előtérrendszer, Csatlakozás állapotalapú háttérszolgáltatáshoz a Service Fabricben

A sorozat első részében a következőkkel ismerkedhet meg:

  • ASP.NET Core Web API-szolgáltatás létrehozása állapotalapú megbízható szolgáltatásként
  • ASP.NET Core Web-alkalmazásszolgáltatás létrehozása állapot nélküli webszolgáltatásként
  • A fordított proxy használata az állapotalapú szolgáltatással folytatott kommunikációhoz

Ebben az oktatóanyag-sorozatban az alábbiakkal ismerkedhet meg:

Előfeltételek

Az oktatóanyag elkezdése előtt:

ASP.NET Web API-szolgáltatás létrehozása megbízható szolgáltatásként

Először hozza létre a szavazóalkalmazás webes kezelőfelületét az ASP.NET Core használatával. Az ASP.NET Core egy egyszerűsített, platformfüggetlen webes fejlesztési keretrendszer, amely segítségével modern webes felhasználói felületeket és webes API-kat hozhat létre. Az ASP.NET Core Service Fabricbe történő integrálásának teljes megértéséhez mindenképpen javasolt az ASP.NET Core a Service Fabric Reliable Services szolgáltatásban való használatát ismertető cikk alapos elolvasása. Egyelőre az első lépésekhez elég, ha elvégzi ezt az oktatóanyagot. Az ASP.NET Core-ról az ASP.NET Core dokumentációjában találhat további információt.

  1. Indítsa el rendszergazdaként a Visual Studiót.

  2. Hozzon létre egy projektet a File-New-Project>> paranccsal.

  3. Az Új projekt párbeszédpanelen válassza a Cloud > Service Fabric-alkalmazás lehetőséget.

  4. Adjon nevet az alkalmazásnak (Voting), majd kattintson az OK gombra.

    A Visual Studio Új projekt párbeszédpanelje

  5. Az Új Service Fabric-szolgáltatás oldalon válassza ki az Állapot nélküli ASP.NET Core elemet, adjon nevet a szolgáltatásnak (VotingWeb), majd kattintson az OK gombra.

    Az ASP.NET-webszolgáltatás kiválasztása az új szolgáltatás párbeszédpanelen

  6. A következő oldalon az ASP.NET Core projektsablonjai találhatók. A jelen oktatóanyag esetében válassza ki a Webalkalmazás (Model-View-Controller) lehetőséget, majd kattintson az OK gombra.

    ASP.NET-projekt típusának kiválasztása

    A Visual Studio létrehoz egy alkalmazás- és egy szolgáltatásprojektet, és megjeleníti őket a Megoldáskezelőben.

    A Megoldáskezelő az alkalmazás az ASP.NET Core Web API szolgáltatással történő létrehozása után

A site.js fájl frissítése

Nyissa meg a wwwroot/js/site.js fájlt. Cserélje le annak tartalmát a kezdőlapnézetek által használt következő JavaScripttel, majd mentse a módosításokat.

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;
            })
    };
}]);

Az Index.cshtml fájl frissítése

Nyissa meg a Views/Home/Index.cshtml fájlt, amely a kezdőlapvezérlő egyedi nézete. Cserélje le annak tartalmát a következőkkel, majd mentse a módosításokat.

@{
    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>

A _Layout.cshtml fájl frissítése

Nyissa meg a Views/Shared/_Layout.cshtml fájlt, amely az ASP.NET-alkalmazás alapértelmezett elrendezését tartalmazza. Cserélje le annak tartalmát a következőkkel, majd mentse a módosításokat.

<!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>

A VotingWeb.cs fájl frissítése

Nyissa meg a VotingWeb.cs fájlt, amely létrehozza az ASP.NET Core WebHostot az állapotmentes szolgáltatáson belül a WebListener webkiszolgáló használatával.

Adja hozzá az using System.Net.Http; direktívát a fájl elejéhez.

Cserélje le a CreateServiceInstanceListeners() függvényt a következő kóddal, majd mentse a módosításokat.

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();
                    }))
    };
}

Adja meg a következő GetVotingDataServiceName metódust is a CreateServiceInstanceListeners() alatt, és mentse a módosításokat. A GetVotingDataServiceName lekérdezéskor visszaadja a szolgáltatás nevét.

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

A VotesController.cs fájl hozzáadása

Adjon hozzá egy vezérlőt, amely meghatározza a szavazási műveleteket. Kattintson a jobb gombbal a Vezérlők mappára, majd válassza az Add-New item-Visual>> C#->ASP.NET Core-Class> elemet. A fájlnak adja a VotesController.cs nevet, majd kattintson a Hozzáadás gombra.

Cserélje le a VotesController.cs fájl tartalmát a következőkre, majd mentse a módosításokat. A későbbiekben, a VotesController.cs fájl frissítése során ez a fájl úgy módosul, hogy a háttérszolgáltatásból a szavazás adatait olvasni és írni is tudja. Egyelőre a vezérlő statikus sztringadatokat ad vissza a nézetben.

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);
        }
     }
}

A figyelőport konfigurálása

A VotingWeb kezelőfelületi szolgáltatás létrehozásakor a Visual Studio véletlenszerűen kiválaszt egy portot, amelyen a szolgáltatás a figyelést végzi. A VotingWeb szolgáltatás az alkalmazás kezelőfelületeként működik, és fogadja a külső forgalmat, úgyhogy rendeljük ezt a szolgáltatást egy rögzített, jól ismert porthoz. A szolgáltatásjegyzék deklarálja a szolgáltatásvégpontokat.

A Megoldáskezelőben nyissa meg a következőt: VotingWeb/PackageRoot/ServiceManifest.xml. Keresse meg az Endpoint (Végpont) elemet a Resources (Erőforrások) szakaszban, és módosítsa a Port értékét 8080-ra. Az alkalmazás helyi üzembe helyezéséhez és futtatásához az alkalmazásfigyelő-portnak a számítógépen megnyitva és elérhető állapotban kell lennie.

<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>

Az alkalmazás URL-címének tulajdonságértékét is frissítse a szavazási projektben, így a webböngésző a megfelelő portot nyitja meg, amikor hibakeresést hajt végre az alkalmazásban. A Megoldáskezelőben válassza ki a Voting projektet, és frissítse az Alkalmazás URL-címe tulajdonságot 8080-ra.

A szavazóalkalmazás helyi üzembe helyezése és futtatása

Most már futtathatja a szavazóalkalmazást a hibakereséshez. A Visual Studióban nyomja le az F5 billentyűt, hogy hibakeresési módban üzembe helyezze az alkalmazást a helyi Service Fabric-fürtön. Az alkalmazást nem lehet majd futtatni, ha korábban nem rendszergazdaként nyitotta meg a Visual Studiót.

Megjegyzés

Az alkalmazás első helyi üzembe helyezésekor a Visual Studio létrehoz egy helyi hibakeresési Service Fabric-fürtöt. A fürt létrehozása eltarthat egy ideig. A fürt létrehozási állapota a Visual Studio kimeneti ablakában jelenik meg.

A szavazóalkalmazás helyi Service Fabric-fürtön való üzembe helyezése után a webalkalmazás automatikusan megnyílik egy böngészőlapon, és a következőképpen kell kinéznie:

ASP.NET Core-kezelőfelület

Az alkalmazás hibakeresésének leállításához lépjen vissza a Visual Studióba, és nyomja le a Shift + F5 billentyűparancsot.

Állapotalapú háttérszolgáltatás hozzáadása az alkalmazáshoz

Most, hogy az alkalmazásban egy ASP.NET Web API-szolgáltatás fut, adjon hozzá egy állapotalapú megbízható szolgáltatást, hogy adatokat tárolhasson az alkalmazásban.

A Service Fabric megbízható gyűjtemények használatával konzisztens módon és megbízhatóan tárolja az adatokat a szolgáltatásban. A megbízható gyűjtemények olyan, magas rendelkezésre állású és megbízható gyűjteményosztályok, amelyeket mindenki jól ismerhet, aki már használt C#-gyűjteményeket.

Ebben az oktatóanyagban létrehoz egy szolgáltatást, amely egy számlálóértéket tárol egy megbízható gyűjteményben.

  1. A Megoldáskezelő kattintson a jobb gombbal a Szolgáltatások elemre a szavazóalkalmazás projektjében, és válassza a Hozzáadás –> Új Service Fabric-szolgáltatás... lehetőséget.

  2. Az Új Service Fabric-szolgáltatás párbeszédablakban válassza az Állapotalapú ASP.NET Core lehetőséget, nevezze el a szolgáltatást (VotingData), majd nyomja le az OK gombot.

    A szolgáltatásprojekt létrehozása után az alkalmazás két szolgáltatást fog tartalmazni. Miközben létrehozza az alkalmazást, hasonlóképpen adhat hozzá további szolgáltatásokat. Mindegyik – a többitől függetlenül – verziószámmal ellátható és frissíthető.

  3. A következő oldalon az ASP.NET Core projektsablonjai találhatók. A jelen oktatóanyaghoz válassza az API lehetőséget.

    A Visual Studio létrehoz egy VotingData nevű szolgáltatási projektet, és megjeleníti azt a Megoldáskezelőben.

    Megoldáskezelő

A VoteDataController.cs fájl hozzáadása

A VotingData projektben kattintson a jobb gombbal a Vezérlők mappára, majd válassza az Add-New item-Class> (Új elemosztály> hozzáadása) lehetőséget. A fájlnak adja a VoteDataController.cs nevet, és kattintson a Hozzáadás parancsra. Cserélje le a fájl tartalmát a következőkkel, majd mentse a módosításokat.

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();
                }
            }
        }
    }
}

A szolgáltatások összekapcsolása

A következő lépésben két szolgáltatást fog összekapcsolni, majd beállítani az előtér-webalkalmazást úgy, hogy az lekérje a szavazási információt a háttérszolgáltatásból, majd beállítsa azt.

A Service Fabric teljes rugalmasságot biztosít a megbízható szolgáltatásokkal folytatott kommunikáció terén. Egy alkalmazáson belül előfordulhat, hogy TCP-n keresztül elérhető szolgáltatások vannak. Elképzelhető, hogy más szolgáltatások egy HTTP REST API-n keresztül, megint más szolgáltatások pedig webes szoftvercsatornákon keresztül érhetők el. A rendelkezésre álló lehetőségekről és azok kompromisszumairól a szolgáltatásokkal folytatott kommunikációt ismertető részben találhat további információt.

Ez az oktatóanyag az ASP.NET Core Web API-t és a Service Fabric fordított proxyt használja, hogy a VotingWeb webes kezelőfelületi szolgáltatás kommunikálhasson a háttérbeli VotingData szolgáltatással. A fordított proxy alapértelmezés szerint a 19081-es port használatára van konfigurálva, és alkalmasnak kell lennie ehhez az oktatóanyaghoz. A fordított proxyport a fürt beállításához használt Azure Resource Manager-sablonban van beállítva. A használt portot a Microsoft.ServiceFabric/clusters erőforrás fürtsablonblonjában tudja megkeresni:

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

A helyi fejlesztési fürtben használt fordított proxyport megkereséséhez tekintse meg a HttpApplicationGatewayEndpoint elemet a helyi Service Fabric-fürt jegyzékfájljában:

  1. Nyisson meg egy böngészőablakot, és navigáljon http://localhost:19080 a Service Fabric Explorer eszköz megnyitásához.
  2. Válassza a Fürt –> Jegyzék lehetőséget.
  3. Jegyezze fel a HttpApplicationGatewayEndpoint elem portját. Ez alapértelmezés szerint a 19081-es port. Ha mégsem az, akkor módosítania kell a portot a következő VotesController.cs kód GetProxyAddress metódusában.

A VotesController.cs fájl frissítése

A VotingWeb projektben nyissa meg a Controllers/VotesController.cs fájlt. Cserélje le a VotesController osztálydefiníció tartalmát a következőkkel, majd mentse a módosításokat. Ha az előző lépésben kikeresett fordítottproxy-port nem a 19081-es, módosítsa a GetProxyAddress metódusban használt portot a 19081-esről a talált portra.

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';
    }
}

A mintául szolgáló szavazóalkalmazás bemutatása

A szavazóalkalmazás két szolgáltatásból áll:

  • Webes kezelőfelületi szolgáltatás (VotingWeb) – Olyan ASP.NET Core webes kezelőfelületi szolgáltatás, amely kiszolgálja a weboldalt, és webes API-kat biztosít a háttérszolgáltatással folytatott kommunikációhoz.
  • Háttérszolgáltatás (VotingData) – Olyan ASP.NET Core webszolgáltatás, amely egy API-t biztosít a szavazási eredmények tárolásához egy megbízható, lemezen őrzött szótárban.

Alkalmazásdiagram

Amikor szavazatot adnak le az alkalmazásban, az alábbi eseményekre kerül sor:

  1. A JavaScript HTTP PUT kérelemként elküldi a szavazati kérést a webes API-nak a webes kezelőfelületi szolgáltatásban.

  2. A webes kezelőfelületi szolgáltatás egy proxy segítségével megkeresi és továbbítja a HTTP PUT kérelmet a háttérszolgáltatásnak.

  3. A háttérszolgáltatás fogadja a bejövő kérelmet, és egy megbízható szótárban tárolja a frissített eredményt, amelyet a fürt több csomópontjára is replikál, és egy lemezen őriz. Az alkalmazás összes adata a fürtön tárolódik, így nincs szükség adatbázisra.

Hibakeresés a Visual Studióban

A Visual Studióban történő hibakeresés során egy helyi Service Fabric fejlesztési fürtöt használ. Arra is lehetősége van, hogy a hibakeresési folyamatot a saját forgatókönyvéhez igazítsa. Ebben az alkalmazásban az adatokat a háttérszolgáltatásban egy megbízható szótár segítségével tárolja. A Visual Studio alapértelmezés szerint a hibakereső leállításakor eltávolítja az alkalmazást. Az alkalmazás eltávolításával a háttérszolgáltatásban tárolt adatok is el lesznek távolítva. Ha szeretné megtartani az adatokat a hibakeresési munkamenetek között, akkor módosítania kell az Application Debug Mode (Alkalmazás hibakeresési módja) tulajdonságot a Voting (Szavazás) projektben a Visual Studióban.

Ha szeretné megtekinteni, hogy mi történik a kódban, hajtsa végre a következő lépéseket:

  1. Nyissa meg a VotingWeb\VotesController.cs fájlt, és állítson be egy töréspontot a webes API Put metódusában (72. sor).

  2. Nyissa meg a VotingData\VoteDataController.cs fájlt, és állítson be egy töréspontot a webes API Put metódusában (54. sor).

  3. Nyomja le az F5 billentyűt az alkalmazás hibakeresési módban való elindításához.

  4. Térjen vissza a böngészőhöz, és kattintson egy szavazási lehetőségre vagy adjon meg egy újat. Az első töréspont a webes kezelőfelület API-vezérlőjében jelentkezik.

    1. A böngészőben futó JavaScript ekkor küld kérelmet a webes kezelőfelületi szolgáltatás API-vezérlőjének.

      Szavazási kezelőfelületi szolgáltatás hozzáadása

    2. Elsőként hozza létre a ReverseProxyra mutató URL-címet a háttérszolgáltatás számára (1).

    3. Ezután küldje el a HTTP PUT kérést a ReverseProxynak (2).

    4. Végül küldje vissza a választ a háttérszolgáltatásból az ügyfélhez (3).

  5. A folytatáshoz nyomja le az F5 billentyűt.

    1. Ezzel elérte a háttérszolgáltatás töréspontját.

      Szavazási háttérszolgáltatás hozzáadása

    2. A metódus első sorában (1) a StateManager használatával egy counts nevű megbízható szótárt kérhet le vagy adhat hozzá.

    3. A megbízható szótárakban tárolt értékekkel folytatott mindennemű interakcióhoz tranzakcióra van szükség, amelyet ez a using utasítás (2) hoz létre.

    4. A tranzakcióban frissítse a szavazási lehetőséghez tartozó kulcs értékét, majd véglegesítse a műveletet (3). Ha a véglegesítési metódus visszatért, az adatok frissülnek a szótárban, és a fürt egyéb csomópontjaira is replikálódnak. Az adatok ettől fogva biztonságosan tárolódnak a fürtön, és a háttérszolgáltatás feladatait más csomópontok is átvehetik, míg az adatok továbbra is elérhetők maradnak.

  6. A folytatáshoz nyomja le az F5 billentyűt.

A hibakeresési munkamenet leállításához nyomja le a Shift+F5 billentyűkombinációt.

Következő lépések

Az oktatóanyag jelen részében megismerkedhetett a következőkkel:

  • ASP.NET Core Web API-szolgáltatás létrehozása állapotalapú megbízható szolgáltatásként
  • ASP.NET Core Web-alkalmazásszolgáltatás létrehozása állapot nélküli webszolgáltatásként
  • A fordított proxy használata az állapotalapú szolgáltatással folytatott kommunikációhoz

Folytassa a következő oktatóanyaggal: