Přístup ke vzdáleným datům

Poznámka:

Tato elektronická kniha byla publikována na jaře roku 2017 a od té doby nebyla aktualizována. Existuje mnoho v knize, která zůstává cenná, ale některé materiály jsou zastaralé.

Mnoho moderních webových řešení využívá webové služby hostované webovými servery k poskytování funkcí vzdáleným klientským aplikacím. Operace, které webová služba zveřejňuje, tvoří webové rozhraní API.

Klientské aplikace by měly být schopné využívat webové rozhraní API bez znalosti způsobu implementace dat nebo operací, které rozhraní API zveřejňuje. To vyžaduje, aby rozhraní API dodržovalo běžné standardy, které klientské aplikaci a webové službě umožňují odsouhlasit, které formáty dat se mají použít, a strukturu dat, která se vyměňují mezi klientskými aplikacemi a webovou službou.

Úvod do převodu stavu reprezentace

Representational State Transfer (REST) je styl architektury pro vytváření distribuovaných systémů založených na hypermedia. Hlavní výhodou modelu REST je, že je založená na otevřených standardech a neváže implementaci modelu ani klientských aplikací, které k němu přistupují k jakékoli konkrétní implementaci. Webovou službu REST je proto možné implementovat pomocí Microsoft ASP.NET Core MVC a klientské aplikace by mohly vyvíjet pomocí libovolného jazyka a sady nástrojů, které můžou generovat požadavky HTTP a analyzovat odpovědi HTTP.

Model REST používá navigační schéma, které představuje objekty a služby v síti, označované jako prostředky. Systémy, které implementují REST, obvykle používají protokol HTTP k přenosu požadavků na přístup k těmto prostředkům. V takových systémech klientská aplikace odešle požadavek ve formě identifikátoru URI, který identifikuje prostředek, a metodu HTTP (například GET, POST, PUT nebo DELETE), která označuje operaci, která se má provést s daným prostředkem. Tělo požadavku HTTP obsahuje všechna data potřebná k provedení operace.

Poznámka:

REST definuje bezstavový model žádosti. Proto požadavky HTTP musí být nezávislé a mohou nastat v libovolném pořadí.

Odpověď požadavku REST využívá standardní stavové kódy HTTP. Například požadavek, který vrací platná data, by měl obsahovat kód odpovědi HTTP 200 (OK), zatímco požadavek, který nenajde nebo odstraní zadaný prostředek, by měl vrátit odpověď, která obsahuje stavový kód HTTP 404 (Nenalezena).

Webové rozhraní RESTful zpřístupňuje sadu připojených prostředků a poskytuje základní operace, které aplikaci umožňují manipulovat s těmito prostředky a snadno se mezi nimi pohybovat. Z tohoto důvodu jsou identifikátory URI, které představují typické webové rozhraní RESTful, orientované na data, která zveřejňuje, a používají zařízení poskytovaná protokolem HTTP k provozování těchto dat.

Data zahrnutá klientskou aplikací v požadavku HTTP a odpovídající zprávy odpovědí z webového serveru mohou být prezentovány v různých formátech, označovaných jako typy médií. Když klientská aplikace odešle požadavek, který vrací data v textu zprávy, může zadat typy médií, které může zpracovat v Accept hlavičce požadavku. Pokud webový server podporuje tento typ média, může odpovědět odpovědí obsahující hlavičku Content-Type , která určuje formát dat v textu zprávy. Potom je zodpovědností klientské aplikace analyzovat zprávu odpovědi a správně interpretovat výsledky v textu zprávy.

Další informace o rozhraní REST najdete v tématu Návrh rozhraní API a implementace rozhraní API.

Využívání rozhraní RESTful API

Mobilní aplikace eShopOnContainers používá model Model-View-ViewModel (MVVM) a prvky modelu modelu představují entity domény použité v aplikaci. Třídy kontroleru a úložiště v referenční aplikaci eShopOnContainers přijímají a vrací mnoho z těchto objektů modelu. Proto se používají jako objekty pro přenos dat (DTO), které obsahují všechna data předávaná mezi mobilní aplikací a kontejnerizovanými mikroslužbami. Hlavní výhodou používání DTO pro předávání dat a přijímání dat z webové služby je, že přenosem více dat v rámci jednoho vzdáleného volání může aplikace snížit počet vzdálených volání, která je potřeba provést.

Vytváření webových požadavků

Mobilní aplikace eShopOnContainers používá HttpClient třídu k provádění požadavků přes PROTOKOL HTTP, přičemž json se používá jako typ média. Tato třída poskytuje funkce pro asynchronní odesílání požadavků HTTP a přijímání odpovědí HTTP z identifikovaného prostředku URI. Třída HttpResponseMessage představuje zprávu odpovědi HTTP přijatou z rozhraní REST API po provedení požadavku HTTP. Obsahuje informace o odpovědi, včetně stavového kódu, záhlaví a libovolného textu. Třída HttpContent představuje tělo HTTP a hlavičky obsahu, například Content-Type a Content-Encoding. Obsah lze číst pomocí některé z ReadAs metod, například ReadAsStringAsync a ReadAsByteArrayAsyncv závislosti na formátu dat.

Vytvoření požadavku GET

Třída CatalogService slouží ke správě procesu načítání dat z mikroslužby katalogu. RegisterDependencies V metodě ve ViewModelLocator třídě CatalogService je třída registrována jako typ mapování na ICatalogService typ s kontejnerem injektáže závislostí Autofac. Když je poté vytvořena instance CatalogViewModel třídy, jeho konstruktor přijme ICatalogService typ, který Autofac přeloží, vrací instanci CatalogService třídy. Další informace o injektáži závislostí naleznete v tématu Úvod do injektáže závislostí.

Obrázek 10-1 ukazuje interakci tříd, které čtou data katalogu z mikroslužby katalogu pro zobrazení pomocí CatalogView.

Retrieving data from the catalog microservice

Obrázek 10–1: Načítání dat z mikroslužby katalogu

CatalogView Při přechodu na metodu OnInitializeCatalogViewModel ve třídě je volána. Tato metoda načte data katalogu z mikroslužby katalogu, jak je znázorněno v následujícím příkladu kódu:

public override async Task InitializeAsync(object navigationData)  
{  
    ...  
    Products = await _productsService.GetCatalogAsync();  
    ...  
}

Tato metoda volá GetCatalogAsync metodu CatalogService instance, která byla vložena do CatalogViewModel autofacu. Následující příklad kódu ukazuje metodu GetCatalogAsync :

public async Task<ObservableCollection<CatalogItem>> GetCatalogAsync()  
{  
    UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);  
    builder.Path = "api/v1/catalog/items";  
    string uri = builder.ToString();  

    CatalogRoot catalog = await _requestProvider.GetAsync<CatalogRoot>(uri);  
    ...  
    return catalog?.Data.ToObservableCollection();            
}

Tato metoda sestaví identifikátor URI, který identifikuje prostředek, do kterého se požadavek odešle, a použije RequestProvider třídu k vyvolání metody GET HTTP u prostředku před vrácením výsledků do CatalogViewModelprostředku . Třída RequestProvider obsahuje funkce, které odešle požadavek ve formě identifikátoru URI, který identifikuje prostředek, metodu HTTP, která označuje operaci, která má být provedena s daným prostředkem, a tělo obsahující všechna data potřebná k provedení operace. Informace o tom, jak RequestProvider se třída vloží do CatalogService classinjektáže závislostí, naleznete v tématu Úvod do injektáže závislostí.

Následující příklad kódu ukazuje metodu GetAsyncRequestProvider ve třídě:

public async Task<TResult> GetAsync<TResult>(string uri, string token = "")  
{  
    HttpClient httpClient = CreateHttpClient(token);  
    HttpResponseMessage response = await httpClient.GetAsync(uri);  

    await HandleResponse(response);  
    string serialized = await response.Content.ReadAsStringAsync();  

    TResult result = await Task.Run(() =>   
        JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings));  

    return result;  
}

Tato metoda volá metodu CreateHttpClient , která vrací instanci HttpClient třídy s příslušnou sadou hlaviček. Pak odešle asynchronní požadavek GET do prostředku identifikovaného identifikátorem URI s odpovědí uloženou HttpResponseMessage v instanci. Metoda HandleResponse se pak vyvolá, což vyvolá výjimku, pokud odpověď neobsahuje úspěšný stavový kód HTTP. Pak se odpověď přečte jako řetězec, převede se z JSON na CatalogRoot objekt a vrátí se do objektu CatalogService.

Metoda CreateHttpClient je znázorněna v následujícím příkladu kódu:

private HttpClient CreateHttpClient(string token = "")  
{  
    var httpClient = new HttpClient();  
    httpClient.DefaultRequestHeaders.Accept.Add(  
        new MediaTypeWithQualityHeaderValue("application/json"));  

    if (!string.IsNullOrEmpty(token))  
    {  
        httpClient.DefaultRequestHeaders.Authorization =   
            new AuthenticationHeaderValue("Bearer", token);  
    }  
    return httpClient;  
}

Tato metoda vytvoří novou instanci HttpClient třídy a nastaví Accept hlavičku všech požadavků provedených HttpClient instancí na application/json, což znamená, že očekává, že obsah jakékoli odpovědi bude formátován pomocí JSON. Pokud byl přístupový token předán jako argument metodě CreateHttpClient , přidá se do Authorization hlavičky všech požadavků provedených HttpClient instancí s předponou řetězce Bearer. Další informace o autorizaci najdete v tématu Autorizace.

Když metoda GetAsync ve RequestProvider volání HttpClient.GetAsynctřídy , Items metoda ve CatalogController třídě v catalog.API projektu je vyvolána, což je znázorněno v následujícím příkladu kódu:

[HttpGet]  
[Route("[action]")]  
public async Task<IActionResult> Items(  
    [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)  
{  
    var totalItems = await _catalogContext.CatalogItems  
        .LongCountAsync();  

    var itemsOnPage = await _catalogContext.CatalogItems  
        .OrderBy(c=>c.Name)  
        .Skip(pageSize * pageIndex)  
        .Take(pageSize)  
        .ToListAsync();  

    itemsOnPage = ComposePicUri(itemsOnPage);  
    var model = new PaginatedItemsViewModel<CatalogItem>(  
        pageIndex, pageSize, totalItems, itemsOnPage);             

    return Ok(model);  
}

Tato metoda načte data katalogu z databáze SQL pomocí EntityFramework a vrátí je jako zprávu odpovědi, která obsahuje úspěšný stavový kód HTTP a kolekci instancí formátovaných CatalogItem json.

Vytvoření požadavku POST

Třída BasketService se používá ke správě procesu načítání a aktualizace dat pomocí mikroslužby košíku. RegisterDependencies V metodě ve ViewModelLocator třídě BasketService je třída registrována jako typ mapování na IBasketService typ s kontejnerem injektáže závislostí Autofac. Když je poté vytvořena instance BasketViewModel třídy, jeho konstruktor přijme IBasketService typ, který Autofac přeloží, vrací instanci BasketService třídy. Další informace o injektáži závislostí naleznete v tématu Úvod do injektáže závislostí.

Obrázek 10-2 znázorňuje interakci tříd, které odesílají data košíku zobrazená pomocí košíku BasketViewdo mikroslužby košíku.

Sending data to the basket microservice

Obrázek 10–2: Odesílání dat do mikroslužby košíku

Při přidání položky do nákupního košíku je ReCalculateTotalAsync volána metoda ve BasketViewModel třídě. Tato metoda aktualizuje celkovou hodnotu položek v košíku a odešle data košíku do mikroslužby košíku, jak je znázorněno v následujícím příkladu kódu:

private async Task ReCalculateTotalAsync()  
{  
    ...  
    await _basketService.UpdateBasketAsync(new CustomerBasket  
    {  
        BuyerId = userInfo.UserId,   
        Items = BasketItems.ToList()  
    }, authToken);  
}

Tato metoda volá UpdateBasketAsync metodu BasketService instance, která byla vložena do BasketViewModel autofacu. Následující metoda ukazuje metodu UpdateBasketAsync :

public async Task<CustomerBasket> UpdateBasketAsync(CustomerBasket customerBasket, string token)  
{  
    UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint);  
    string uri = builder.ToString();  
    var result = await _requestProvider.PostAsync(uri, customerBasket, token);  
    return result;  
}

Tato metoda sestaví identifikátor URI, který identifikuje prostředek, do kterého se požadavek odešle, a použije RequestProvider třídu k vyvolání metody POST HTTP prostředku před vrácením výsledků do BasketViewModelprostředku . Všimněte si, že přístupový token získaný z IdentityServer během procesu ověřování je nutný k autorizaci požadavků na mikroslužbu košíku. Další informace o autorizaci najdete v tématu Autorizace.

Následující příklad kódu ukazuje jednu z PostAsync metod ve RequestProvider třídě:

public async Task<TResult> PostAsync<TResult>(  
    string uri, TResult data, string token = "", string header = "")  
{  
    HttpClient httpClient = CreateHttpClient(token);  
    ...  
    var content = new StringContent(JsonConvert.SerializeObject(data));  
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");  
    HttpResponseMessage response = await httpClient.PostAsync(uri, content);  

    await HandleResponse(response);  
    string serialized = await response.Content.ReadAsStringAsync();  

    TResult result = await Task.Run(() =>  
        JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings));  

    return result;  
}

Tato metoda volá metodu CreateHttpClient , která vrací instanci HttpClient třídy s příslušnou sadou hlaviček. Pak odešle asynchronní požadavek POST na prostředek identifikovaný identifikátorem URI, se serializovanými daty košíku odesílanými ve formátu JSON a odpovědí uloženou HttpResponseMessage v instanci. Metoda HandleResponse se pak vyvolá, což vyvolá výjimku, pokud odpověď neobsahuje úspěšný stavový kód HTTP. Odpověď se pak přečte jako řetězec, převede se z JSON na CustomerBasket objekt a vrátí se do objektu BasketService. Další informace o CreateHttpClient metodě naleznete v tématu Vytvoření požadavku GET.

Když metoda PostAsync ve RequestProvider volání HttpClient.PostAsynctřídy , Post metoda ve BasketController třídě v projektu Basket.API je vyvolána, což je znázorněno v následujícím příkladu kódu:

[HttpPost]  
public async Task<IActionResult> Post([FromBody]CustomerBasket value)  
{  
    var basket = await _repository.UpdateBasketAsync(value);  
    return Ok(basket);  
}

Tato metoda používá instanci RedisBasketRepository třídy k zachování dat košíku do mezipaměti Redis a vrací je jako zprávu odpovědi, která obsahuje úspěšný stavový kód HTTP a instanci ve formátu CustomerBasket JSON.

Vytvoření požadavku DELETE

Obrázek 10-3 znázorňuje interakce tříd, které odstraňují data košíku z mikroslužby košíku pro .CheckoutView

Deleteing data from the basket microservice

Obrázek 10–3: Odstranění dat z mikroslužby košíku

Při vyvolání procesu rezervace je volána CheckoutAsync metoda ve CheckoutViewModel třídě. Tato metoda vytvoří novou objednávku před vymazáním nákupního košíku, jak je znázorněno v následujícím příkladu kódu:

private async Task CheckoutAsync()  
{  
    ...  
    await _basketService.ClearBasketAsync(_shippingAddress.Id.ToString(), authToken);  
    ...  
}

Tato metoda volá ClearBasketAsync metodu BasketService instance, která byla vložena do CheckoutViewModel autofacu. Následující metoda ukazuje metodu ClearBasketAsync :

public async Task ClearBasketAsync(string guidUser, string token)  
{  
    UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint);  
    builder.Path = guidUser;  
    string uri = builder.ToString();  
    await _requestProvider.DeleteAsync(uri, token);  
}

Tato metoda sestaví identifikátor URI, který identifikuje prostředek, do kterého se požadavek odešle, a pomocí RequestProvider třídy vyvolá metodu DELETE HTTP v prostředku. Všimněte si, že přístupový token získaný z IdentityServer během procesu ověřování je nutný k autorizaci požadavků na mikroslužbu košíku. Další informace o autorizaci najdete v tématu Autorizace.

Následující příklad kódu ukazuje metodu DeleteAsyncRequestProvider ve třídě:

public async Task DeleteAsync(string uri, string token = "")  
{  
    HttpClient httpClient = CreateHttpClient(token);  
    await httpClient.DeleteAsync(uri);  
}

Tato metoda volá metodu CreateHttpClient , která vrací instanci HttpClient třídy s příslušnou sadou hlaviček. Potom odešle asynchronní požadavek DELETE do prostředku identifikovaného identifikátorem URI. Další informace o CreateHttpClient metodě naleznete v tématu Vytvoření požadavku GET.

Když metoda DeleteAsync ve RequestProvider volání HttpClient.DeleteAsynctřídy , Delete metoda ve BasketController třídě v projektu Basket.API je vyvolána, což je znázorněno v následujícím příkladu kódu:

[HttpDelete("{id}")]  
public void Delete(string id)  
{  
    _repository.DeleteBasketAsync(id);  
}

Tato metoda používá instanci RedisBasketRepository třídy k odstranění dat košíku z mezipaměti Redis.

Ukládaní dat do mezipaměti

Výkon aplikace je možné zlepšit ukládáním často přístupných dat do mezipaměti do rychlého úložiště umístěného v blízkosti aplikace. Pokud se rychlé úložiště nachází blíž k aplikaci než původní zdroj, může ukládání do mezipaměti výrazně zlepšit dobu odezvy při načítání dat.

Nejběžnější formou ukládání do mezipaměti je ukládání do mezipaměti čtení, kde aplikace načítá data odkazem na mezipaměť. Pokud data v mezipaměti nejsou, načtou se z úložiště dat a přidají se do mezipaměti. Aplikace můžou implementovat ukládání do mezipaměti s doplňováním mezipaměti pomocí vzoru doplňování do mezipaměti. Tento vzor určuje, jestli je položka aktuálně v mezipaměti. Pokud položka není v mezipaměti, přečte se z úložiště dat a přidá se do mezipaměti. Další informace najdete v modelu doplňování mezipaměti.

Tip

Ukládání dat do mezipaměti, která se často čtou, a že se mění zřídka. Tato data je možné přidat do mezipaměti na vyžádání při prvním načtení aplikací. To znamená, že aplikace potřebuje načíst data pouze jednou z úložiště dat a že následný přístup může být splněn pomocí mezipaměti.

Distribuované aplikace, jako je referenční aplikace eShopOnContainers, by měly poskytovat jednu nebo obě z následujících mezipamětí:

  • Sdílená mezipaměť, ke které může přistupovat více procesů nebo počítačů.
  • Privátní mezipaměť, ve které se data ukládají místně na zařízení, na kterém běží aplikace.

Mobilní aplikace eShopOnContainers používá privátní mezipaměť, kde se data uchovávají místně na zařízení, na kterém běží instance aplikace. Informace o mezipaměti používané referenční aplikací eShopOnContainers naleznete v tématu Mikroslužby .NET: Architektura pro kontejnerizované aplikace .NET.

Tip

Mezipaměť si můžete představit jako přechodné úložiště dat, které by mohlo kdykoli zmizet. Ujistěte se, že jsou data zachována v původním úložišti dat i v mezipaměti. Pravděpodobnost ztráty dat se pak minimalizuje, pokud mezipaměť přestane být k dispozici.

Správa vypršení platnosti dat

Je nepraktické očekávat, že data uložená v mezipaměti budou vždy konzistentní s původními daty. Data v původním úložišti dat se můžou po uložení do mezipaměti změnit, což způsobí, že data uložená v mezipaměti přestanou být zastaralá. Aplikace by proto měly implementovat strategii, která pomáhá zajistit, aby data v mezipaměti byla co nejaktuálnější, ale můžou také zjišťovat a zpracovávat situace, které vznikají, když se data v mezipaměti stanou zastaralá. Většina mechanismů ukládání do mezipaměti umožňuje nakonfigurovat mezipaměť tak, aby vypršela platnost dat, a proto zkracuje dobu, po kterou můžou být data zahlcená.

Tip

Při konfiguraci mezipaměti nastavte výchozí dobu vypršení platnosti. Mnoho mezipamětí implementuje vypršení platnosti, které zneplatňuje data a odebere je z mezipaměti, pokud k ní není po zadanou dobu přístup. Při výběru období vypršení platnosti je však potřeba věnovat pozornost. Pokud je příliš krátká, data vyprší příliš rychle a výhody ukládání do mezipaměti se sníží. Pokud je příliš dlouhý, rizika dat se stávají zastaralou. Proto by se doba vypršení platnosti měla shodovat se vzorem přístupu pro aplikace, které data používají.

Když vyprší platnost dat uložených v mezipaměti, měla by se z mezipaměti odebrat a aplikace musí načíst data z původního úložiště dat a umístit je zpět do mezipaměti.

Je také možné, že mezipaměť může vyplnit, pokud data zůstanou příliš dlouhou dobu. Proto mohou být žádosti o přidání nových položek do mezipaměti nutné k odebrání některých položek v procesu označovaného jako vyřazení. Ukládání do mezipaměti služby obvykle vyřadí data nejméně nedávno používaným způsobem. Existují však další zásady vyřazení, včetně naposledy použitých zásad a prvního vyřazování. Další informace najdete v tématu Ukládání do mezipaměti Pokyny.

obrázky Ukládání do mezipaměti

Mobilní aplikace eShopOnContainers využívá vzdálené image produktů, které těží z ukládání do mezipaměti. Tyto obrázky se zobrazí ovládacím Image prvku a CachedImage ovládací prvek poskytovaný knihovnou FFImageLoading .

Ovládací Xamarin.FormsImage prvek podporuje ukládání stažených imagí do mezipaměti. Ukládání do mezipaměti je ve výchozím nastavení povolená a image se uloží místně po dobu 24 hodin. Kromě toho je možné u vlastnosti nakonfigurovat CacheValidity čas vypršení platnosti. Další informace naleznete v tématu Stažená image Ukládání do mezipaměti.

Ovládací prvek FFImageLoading CachedImage je náhradou Xamarin.FormsImage ovládacího prvku a poskytuje další vlastnosti, které umožňují doplňkové funkce. Mezi tyto funkce ovládací prvek poskytuje konfigurovatelné ukládání do mezipaměti a podporuje zástupné symboly obrázků při chybě a načítání. Následující příklad kódu ukazuje, jak eShopOnContainers mobilní aplikace používá CachedImage ovládací prvek v ProductTemplate, což je datová šablona používaná ovládacím ListView prvku v CatalogView:

<ffimageloading:CachedImage
    Grid.Row="0"
    Source="{Binding PictureUri}"     
    Aspect="AspectFill">
    <ffimageloading:CachedImage.LoadingPlaceholder>
        <OnPlatform x:TypeArguments="ImageSource">
            <On Platform="iOS, Android" Value="default_campaign" />
            <On Platform="UWP" Value="Assets/default_campaign.png" />
        </OnPlatform>
    </ffimageloading:CachedImage.LoadingPlaceholder>
    <ffimageloading:CachedImage.ErrorPlaceholder>
        <OnPlatform x:TypeArguments="ImageSource">
            <On Platform="iOS, Android" Value="noimage" />
            <On Platform="UWP" Value="Assets/noimage.png" />
        </OnPlatform>
    </ffimageloading:CachedImage.ErrorPlaceholder>
</ffimageloading:CachedImage>

Ovládací CachedImage prvek nastaví LoadingPlaceholder vlastnosti a ErrorPlaceholder vlastnosti na image specifické pro platformu. Vlastnost LoadingPlaceholder určuje obrázek, který se má zobrazit při načtení obrázku určeného Source vlastností, a ErrorPlaceholder vlastnost určuje obrázek, který se má zobrazit, pokud dojde k chybě při pokusu o načtení obrázku určeného vlastností Source .

Jak název napovídá, CachedImage ovládací prvek ukládá vzdálené obrázky do mezipaměti na zařízení po dobu určenou hodnotou CacheDuration vlastnosti. Pokud tato hodnota vlastnosti není explicitně nastavená, použije se výchozí hodnota 30 dnů.

Zvýšení odolnosti

Všechny aplikace, které komunikují se vzdálenými službami a prostředky, musí být citlivé na přechodné chyby. Mezi přechodné chyby patří momentální ztráta síťového připojení ke službám, dočasná nedostupnost služby nebo vypršení časových limitů, ke kterým dojde, když je služba zaneprázdněná. Tyto chyby jsou často samoopravovány a pokud se akce opakuje po vhodném zpoždění, bude pravděpodobně úspěšná.

Přechodné chyby můžou mít obrovský dopad na vnímanou kvalitu aplikace, i když byla důkladně testována za všech předvídatelných okolností. Aby aplikace, která komunikuje se vzdálenými službami, fungovala spolehlivě, musí být schopná provádět všechny následující akce:

  • Zjistí chyby, kdy k nim dojde, a určí, jestli jsou chyby pravděpodobně přechodné.
  • Zkuste operaci zopakovat, pokud zjistí, že chyba bude pravděpodobně přechodná, a sledujte počet opakování operace.
  • Použijte odpovídající strategii opakování, která určuje počet opakování, zpoždění mezi jednotlivými pokusy a akce, které se mají provést po neúspěšném pokusu.

Toto zpracování přechodných chyb lze dosáhnout zabalením všech pokusů o přístup ke vzdálené službě v kódu, který implementuje vzor opakování.

Vzor opakování

Pokud aplikace zjistí selhání při pokusu o odeslání požadavku do vzdálené služby, může toto selhání zpracovat některým z následujících způsobů:

  • Zkuste operaci zopakovat. Aplikace by mohla žádost o selhání zopakovat okamžitě.
  • Opakování operace po zpoždění Aplikace by měla před opakováním požadavku počkat na vhodnou dobu.
  • Zrušení operace. Aplikace by měla operaci zrušit a nahlásit výjimku.

Strategie opakování by měla být vyladěná tak, aby odpovídala obchodním požadavkům aplikace. Je například důležité optimalizovat počet opakování a interval opakování na operaci, o kterou se pokoušíte. Pokud je operace součástí interakce uživatele, měl by být interval opakování krátký a pouze několik opakování se pokusilo zabránit tomu, aby uživatelé čekali na odpověď. Pokud je operace součástí dlouhotrvajícího pracovního postupu, kdy zrušení nebo restartování pracovního postupu je nákladné nebo časově náročné, je vhodné počkat delší dobu mezi pokusy a opakovat vícekrát.

Poznámka:

Agresivní strategie opakování s minimálním zpožděním mezi pokusy a velkým počtem opakovaných pokusů může snížit výkon vzdálené služby, která běží v blízkosti nebo v kapacitě. Tato strategie opakování by navíc mohla ovlivnit rychlost odezvy aplikace, pokud se neustále pokouší provést neúspěšnou operaci.

Pokud požadavek po několika opakovaných pokusech stále selže, je lepší, aby aplikace zabránila dalším žádostem ve stejném prostředku a ohlásila selhání. Po nastaveném období pak může aplikace provést jeden nebo více požadavků na prostředek, aby se zjistilo, jestli jsou úspěšné. Další informace získáte v článku Vzorce jističe.

Tip

Nikdy implementujte mechanismus s nekonečným počtem opakování. Použijte konečný počet opakování nebo implementujte model Jistič , který službě umožní obnovení.

Mobilní aplikace eShopOnContainers v současné době neimplementuje model opakování při provádění webových požadavků RESTful. CachedImage Ovládací prvek poskytovaný knihovnou FFImageLoading však podporuje zpracování přechodných chyb opakovaným pokusem o načtení image. Pokud se načtení image nezdaří, provede se další pokusy. Počet pokusů je určen vlastností RetryCount a opakování bude probíhat po zpoždění určené vlastností RetryDelay . Pokud tyto hodnoty vlastností nejsou explicitně nastaveny, použijí se jejich výchozí hodnoty – 3 pro RetryCount vlastnost a 250 ms pro RetryDelay vlastnost. Další informace o ovládacím CachedImage prvku najdete v tématu Ukládání do mezipaměti Obrázky.

Referenční aplikace eShopOnContainers implementuje vzor opakování. Další informace, včetně diskuze o tom, jak zkombinovat vzor opakování s HttpClient třídou, najdete v tématu Mikroslužby .NET: Architektura pro kontejnerizované aplikace .NET.

Další informace o vzoru opakování najdete v modelu opakování .

Model Jistič

V některých situacích může dojít k chybám kvůli očekávaným událostem, které trvá déle, než se opraví. Tyto chyby můžou být v rozsahu od částečné ztráty připojení až po úplné selhání služby. V těchto situacích je pro aplikaci zbytečné opakovat operaci, která pravděpodobně nebude úspěšná, a místo toho by měla přijmout, že operace selhala, a odpovídajícím způsobem zpracovat tuto chybu.

Model jističe může bránit aplikaci v opakovaném pokusu o provedení operace, která pravděpodobně selže, a zároveň aplikaci umožnit zjistit, jestli byla chyba vyřešena.

Poznámka:

Účel modelu jističe se liší od vzoru opakování. Model opakování umožňuje aplikaci opakovat operaci v očekávaném očekávání, že bude úspěšná. Model jističe zabraňuje aplikaci v provádění operace, která pravděpodobně selže.

Jistič funguje jako proxy pro operace, které můžou selhat. Proxy server by měl monitorovat počet nedávných selhání, ke kterým došlo, a použít tyto informace k rozhodnutí, jestli operaci povolit pokračování, nebo okamžitě vrátit výjimku.

Mobilní aplikace eShopOnContainers v současné době neimplementuje model jističe. EShopOnContainers však dělá. Další informace naleznete v tématu Mikroslužby .NET: Architektura pro kontejnerizované aplikace .NET.

Tip

Zkombinujte vzory opakování a jističe. Aplikace může zkombinovat vzory opakování a jističe pomocí vzoru opakování k vyvolání operace prostřednictvím jističe. Logika opakovaných pokusů by však měla brát ohled na výjimky vrácené jističem a pokud jistič signalizuje, že chyba není přechodná, neměla by provádět opakované pokusy.

Další informace o vzoru jističe naleznete v modelu Jistič .

Shrnutí

Mnoho moderních webových řešení využívá webové služby hostované webovými servery k poskytování funkcí vzdáleným klientským aplikacím. Operace, které webová služba zpřístupňuje, představují webové rozhraní API a klientské aplikace by měly být schopny využívat webové rozhraní API bez znalosti způsobu implementace dat nebo operací, které rozhraní API zveřejňuje.

Výkon aplikace je možné zlepšit ukládáním často přístupných dat do mezipaměti do rychlého úložiště umístěného v blízkosti aplikace. Aplikace můžou implementovat ukládání do mezipaměti s doplňováním mezipaměti pomocí vzoru doplňování do mezipaměti. Tento vzor určuje, jestli je položka aktuálně v mezipaměti. Pokud položka není v mezipaměti, přečte se z úložiště dat a přidá se do mezipaměti.

Při komunikaci s webovými rozhraními API musí být aplikace citlivé na přechodné chyby. Mezi přechodné chyby patří momentální ztráta síťového připojení ke službám, dočasná nedostupnost služby nebo vypršení časových limitů, ke kterým dojde, když je služba zaneprázdněná. Tyto chyby jsou často samoopravovány a pokud se akce opakuje po vhodném zpoždění, bude pravděpodobně úspěšná. Aplikace by proto měly zabalit všechny pokusy o přístup k webovému rozhraní API v kódu, který implementuje přechodný mechanismus zpracování chyb.