Yoklama tabanlı bir web uygulamasının sınırlamalarını analiz etme
Uygulamanın geçerli mimarisi, bir zamanlayıcı temelinde sunucudan tüm hisse senedi fiyat bilgilerini getirerek hisse senedi bilgilerini raporlar. Bu tasarıma genellikle yoklama temelli tasarım da denir.
Sunucu
Hisse senedi fiyatı bilgileri bir Azure Cosmos DB veritabanında depolanır. BIR HTTP isteği tarafından tetiklendiğinde işlev getStocks
veritabanındaki tüm satırları döndürür.
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,
};
},
});
- Veri alma: Kodun ilk bölümü olan cosmosInput, Cosmos DB'deki
stocks
veritabanında sorgusuylaSELECT * from c
birlikte tablodakistocksdb
tüm öğeleri alır. - Veri döndürme: Kodun ikinci bölümü olan app.http, bu verileri işlevine giriş
context.extraInputs
olarak alır ve ardından yanıt gövdesi olarak istemciye geri döndürür.
İstemci
Örnek istemci, kullanıcı arabirimini oluşturmak için Vue.js ve API'ye yönelik istekleri işlemek için Fetch istemcisini kullanır.
HTML sayfası, hisse senedi istemek için sunucuya beş saniyede bir istek göndermek için bir zamanlayıcı kullanır. Yanıt, bir hisse senedi dizisi döndürür ve bunlar kullanıcıya gösterilir.
<!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();
}
});
startPoll
Yöntem yoklama işlemine başladıktan sonra beş update
saniyede bir çağrılır. yönteminin update
içinde API uç noktasına bir GET isteği gönderilir /api/getStocks
ve sonuç olarak ayarlanır app.stocks
ve bu da kullanıcı arabirimini güncelleştirir.
Sunucu ve istemci kodu nispeten basittir: tüm verileri alın, tüm verileri görüntüleyin. Analizimizde bulduğumuz gibi bu basitlik bazı sınırlamaları da beraberinde getiriyor.
Prototip çözümün analizi
Tailwind Traders mühendisi olarak bu zamanlayıcı tabanlı yoklama yaklaşımının bazı dezavantajlarını belirlediniz.
Gereksiz API istekleri: Zamanlayıcı tabanlı yoklama prototipinde istemci uygulaması, temel alınan verilerde değişiklik yapılıp yapılmadığı konusunda sunucuyla iletişim kurar.
Gereksiz sayfa yenilemeleri: Veriler sunucudan döndürüldükten sonra, hiçbir veri değişmemiş olsa bile web sayfasında hisse senetleri listesinin tamamı güncelleştirilir. Bu yoklama mekanizması verimsiz bir çözümdür.
Yoklama aralıkları: Senaryonuz için en iyi yoklama aralığını seçmek de zor bir görevdir. Yoklama, sizi arka uca yapılan her çağrının maliyetinin ne kadar olacağı ve uygulamanızın yeni verilere ne kadar hızlı yanıt vereceği arasında bir seçim yapmaya zorlar. Yeni verilerin kullanılabilir duruma gelmesiyle uygulamanın bunu algılama süresi arasında genellikle gecikmeler olur. Aşağıdaki çizimde bu sorun gösterilir.
En kötü durumda, yeni verilerin algılanmasındaki olası gecikme yoklama aralığına eşit olur. Peki neden daha küçük bir aralık kullanılmıyor?
Veri miktarı: Uygulama ölçeklendirildikçe, istemci ile sunucu arasında değiştirilen veri miktarı sorun haline gelir. Her HTTP istek üst bilgisi, oturumun tanımlama bilgisinin yanı sıra yüzlerce baytlık veri içerir. Tüm bu ek yük, kaynakların özellikle sunucu ağır yük altındayken boşa tüketilmesine neden olur ve sunucuya gereksiz yük bindirir.
Artık prototipi daha iyi bildiğinize göre, artık uygulamayı makinenizde çalıştırmanın zamanı geldi.
CORS’yi destekleme
İşlevler Uygulamasının local.settings.json dosyasında, Host
bölümü aşağıdaki ayarları içerir.
{
"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
}
}
Bu yapılandırma, localhost:3000 konumunda çalışan bir web uygulamasının localhost:7071 adresinde çalışan işlev uygulamasına istekte bulunmasını sağlar. özelliği CORSCredentials
, işlev uygulamasına istekten kimlik bilgisi tanımlama bilgilerini kabul etmelerini söyler.
Çıkış noktaları arası kaynak paylaşımı (CORS), bir etki alanında çalışan web uygulamasının başka bir etki alanındaki kaynaklara erişmesini sağlayan bir HTTP özelliğidir. Web tarayıcıları, bir web sayfasının API'leri farklı etki alanından çağırmasını engelleyen, aynı çıkış noktası ilkesi olarak bilinen bir güvenlik kısıtlaması uygular. CORS, bir etki alanına (çıkış noktası etki alanı) başka etki alanındaki API'leri çağırmasına izin veren güvenli bir yol sağlar.
Yerel olarak çalışırken, CORS sizin için hiçbir zaman yayımlanmayan örneğin local.settings.json dosyasında yapılandırılır. İstemci uygulamasını (birim 7) dağıttığınızda, istemci uygulamasından erişime izin vermek için işlev uygulamasındaki CORS ayarlarını da güncelleştirmeniz gerekir.