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 ReadAsByteArrayAsync
v 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
.
Obrázek 10–1: Načítání dat z mikroslužby katalogu
CatalogView
Při přechodu na metodu OnInitialize
CatalogViewModel
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 CatalogViewModel
prostř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 class
injektáže závislostí, naleznete v tématu Úvod do injektáže závislostí.
Následující příklad kódu ukazuje metodu GetAsync
RequestProvider
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.GetAsync
tří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 BasketView
do mikroslužby košíku.
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 BasketViewModel
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 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.PostAsync
tří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
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 DeleteAsync
RequestProvider
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.DeleteAsync
tří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í služeb do mezipaměti 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 Pokyny k ukládání do mezipaměti.
Ukládání obrázků 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é ukládání obrázků 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 naleznete v tématu Ukládání obrázků do mezipaměti.
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.