Analýza omezení webové aplikace založené na dotazování
Aktuální architektura aplikace hlásí informace o akciích načtením všech informací o cenách akcií ze serveru na základě časovače. Takový design se často označuje jako založený na cyklickém dotazování.
Server
Informace o cenách akcií se ukládají do databáze Azure Cosmos DB. Při aktivaci požadavkem HTTP vrátí funkce getStocks
všechny řádky z databáze.
import { app, input } from "@azure/functions";
const cosmosInput = input.cosmosDB({
databaseName: 'stocksdb',
containerName: 'stocks',
connection: 'COSMOSDB_CONNECTION_STRING',
sqlQuery: 'SELECT * from c',
});
app.http('getStocks', {
methods: ['GET'],
authLevel: 'anonymous',
extraInputs: [cosmosInput],
handler: (request, context) => {
const stocks = context.extraInputs.get(cosmosInput);
return {
jsonBody: stocks,
};
},
});
- Získání dat: První část kódu, cosmosInput, získá všechny položky v
stocks
tabulce s dotazemSELECT * from c
vstocksdb
databázi v Cosmos DB. - Návratová data: Druhá část kódu app.http přijímá tato data do funkce jako vstup a
context.extraInputs
pak je vrátí jako tělo odpovědi zpět klientovi.
Klient
Ukázkový klient používá Vue.js k vytvoření uživatelského rozhraní a klienta Fetch ke zpracování požadavků na rozhraní API.
Stránka HTML používá časovač k odeslání požadavku na server každých pět sekund, aby požádala o akcie. Odpověď vrátí pole akcií, které se pak zobrazí uživateli.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css" integrity="sha256-8B1OaG0zT7uYA572S2xOxWACq9NXYPQ+U5kHPV1bJN4=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<title>Stocks | Enable automatic updates in a web application using Azure Functions and SignalR</title>
</head>
<body>
<!-- BEGIN: Replace markup in this section -->
<div id="app" class="container">
<h1 class="title">Stocks</h1>
<div id="stocks">
<div v-for="stock in stocks" class="stock">
<div class="lead">{{ stock.symbol }}: ${{ stock.price }}</div>
<div class="change">Change:
<span :class="{ 'is-up': stock.changeDirection === '+', 'is-down': stock.changeDirection === '-' }">
{{ stock.changeDirection }}{{ stock.change }}
</span></div>
</div>
</div>
</div>
<!-- END -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js" integrity="sha256-chlNFSVx3TdcQ2Xlw7SvnbLAavAQLO0Y/LBiWX04viY=" crossorigin="anonymous"></script>
<script src="bundle.js" type="text/javascript"></script>
</body>
</html>
import './style.css';
function getApiUrl() {
const backend = process.env.BACKEND_URL;
const url = (backend) ? `${backend}` : ``;
return url;
}
const app = new Vue({
el: '#app',
interval: null,
data() {
return {
stocks: []
}
},
methods: {
async update() {
try {
const url = `${getApiUrl()}/api/getStocks`;
console.log('Fetching stocks from ', url);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
app.stocks = await response.json();
} catch (ex) {
console.error(ex);
}
},
startPoll() {
this.interval = setInterval(this.update, 5000);
}
},
created() {
this.update();
this.startPoll();
}
});
Jakmile metoda startPoll
začne dotazovat, update
volá se metoda každých pět sekund. update
Uvnitř metody se odešle požadavek GET do koncového /api/getStocks
bodu rozhraní API a výsledek je nastavený na app.stocks
, který aktualizuje uživatelské rozhraní.
Server a klientský kód jsou poměrně jednoduché: získat všechna data a zobrazit všechna data. Jak zjistíme v naší analýze, přináší tato jednoduchost určitá omezení.
Analýza prototypového řešení
Jako technik společnosti Tailwind Traders jste identifikovali některé nevýhody tohoto přístupu cyklického dotazování založeného na časovači.
Nepotřebné požadavky rozhraní API: V prototypu dotazování na základě časovače klientská aplikace kontaktuje server bez ohledu na to, jestli v podkladových datech existují změny.
Nepotřebná aktualizace stránky: Po vrácení dat ze serveru se na webové stránce aktualizuje celý seznam akcií, i když se nezměnila žádná data. Takový mechanismus dotazování nepředstavuje efektivní řešení.
Intervaly dotazování: Výběr nejlepšího intervalu dotazování pro váš scénář je také výzvou. Dotazování vás nutí rozhodovat se mezi náklady na každé volání back-endových funkcí a rychlostí, s jakou má aplikace reagovat na nová data. Zpoždění často existují mezi časem, kdy jsou k dispozici nová data, a časem, kdy je aplikace detekuje. Následující obrázek znázorňuje tento problém.
V nejhorším případě je potenciální zpoždění zjištění nových dat rovno intervalu dotazování. Proč tedy nepoužít kratší interval?
Množství dat: Při škálování aplikace se množství dat vyměňovaných mezi klientem a serverem stává problémem. Každá hlavička požadavku HTTP zahrnuje stovky bajtů dat spolu se souborem cookie relace. Tato režie pak zejména v případě velkého vytížení vede k plýtvání prostředky a zbytečně zatěžuje server.
Teď, když jste obeznámeni s prototypem, je čas na spuštění aplikace na vašem počítači.
Podpora mechanismu CORS
V souboru local.settings.json aplikace Host
Functions obsahuje následující nastavení.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "<STORAGE_CONNECTION_STRING>",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
"COSMOSDB_CONNECTION_STRING": "<COSMOSDB_CONNECTION_STRING>"
},
"Host" : {
"LocalHttpPort": 7071,
"CORS": "http://localhost:3000",
"CORSCredentials": true
}
}
Tato konfigurace umožňuje webové aplikaci spuštěné na localhost:3000 vyhovět aplikacím funkcí spuštěným na localhost:7071. Tato vlastnost CORSCredentials
aplikaci funkcí říká, aby z požadavku přijímala soubory cookie s přihlašovacími údaji.
Sdílení prostředků mezi zdroji (CORS) je funkce HTTP, která umožňuje webové aplikaci spuštěné v jedné doméně přistupovat k prostředkům v jiné doméně. Webové prohlížeče implementují omezení zabezpečení označované jako zásada stejného původu, které webové stránce znemožňuje volat rozhraní API v jiné doméně. CORS přináší zabezpečený způsob, jak je možné jedné doméně (tj. původní doméně) povolit volání rozhraní API v jiné doméně.
Při místním spuštění se CORS nakonfiguruje v ukázkovém local.settings.json souboru, který se nikdy nepublikuje. Když nasadíte klientskou aplikaci (7. lekce), musíte také aktualizovat nastavení CORS v aplikaci funkcí tak, aby umožňovala přístup z klientské aplikace.