Analizar las limitaciones de una aplicación web basada en sondeo
La arquitectura actual de la aplicación notifica información sobre acciones mediante la recuperación de cambios desde el servidor en función de un temporizador. Este diseño se suele denominar diseño basado en sondeo.
Antes de analizar las limitaciones, vamos a revisar la arquitectura actual. El servidor es responsable de almacenar la información sobre las acciones y el cliente presenta los datos en el explorador.
En la siguiente unidad vamos a configurar la solución actual en el equipo local.
Servidor
La información sobre el precio de las acciones se almacena en el servidor en una base de datos de Azure Cosmos DB. Cuando se desencadena mediante una solicitud HTTP, la función usa enlaces para devolver el contenido de la base de datos.
La función denominada getStocks
es responsable de leer la información sobre acciones de la base de datos. Como se ha mencionado, la conexión a la base de datos de Azure Cosmos DB se logra mediante un enlace de entrada. Este enlace se configura en el archivo function.json, como se muestra en el siguiente fragmento de código.
{
"bindings": [
{
"type": "httpTrigger",
"authLevel": "anonymous",
"direction": "in",
"name": "req",
"methods": ["get"]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "cosmosDB",
"direction": "in",
"name": "stocks",
"ConnectionStringSetting": "AzureCosmosDBConnectionString",
"databaseName": "stocksdb",
"collectionName": "stocks"
}
]
}
El primer enlace (httpTrigger
) de la matriz define cómo se desencadena la función.
La configuración... | mediante la propiedad: |
---|---|
define la función como una función desencadenada por HTTP | type |
permite solicitudes entrantes no autenticadas | authLevel , direction |
expone el contexto de solicitud a través de un parámetro denominado req |
name |
acepta solicitudes GET | methods |
El segundo enlace (http
) define lo que se devuelve desde la función.
La configuración... | mediante la propiedad: |
---|---|
permite a la función devolver una respuesta HTTP | type , direction |
expone el contexto de respuesta a través de un parámetro denominado res |
name |
El tercer enlace (cosmosDB
) establece una conexión a Azure Cosmos DB.
La configuración... | mediante la propiedad: |
---|---|
convierte en disponibles datos de Azure Cosmos DB cuando se llama a la función | type , direction |
expone los datos a la función a través de un parámetro denominado stocks |
name |
se conecta a los datos de Azure Cosmos DB con una cadena de conexión | ConnectionStringSetting |
apunta a la base de datos stocksdb |
databaseName |
apunta a la colección de datos stocks |
collectionName |
Con estos enlaces, las solicitudes GET a getStocks
convierten los datos en disponibles a través del parámetro stocks
. Como puede ver en el siguiente fragmento de código, el código de función para recuperar información sobre acciones es sencillo gracias a la eficacia de los enlaces de Azure Functions.
module.exports = async function (context, req, stocks) {
context.res.body = stocks;
};
Cliente
El cliente de ejemplo usa Vue.js para crear la interfaz de usuario y el cliente HTTP Axios para controlar las solicitudes a la función.
La página usa un temporizador para enviar una solicitud al servidor cada cinco segundos a fin de solicitar acciones. La respuesta devuelve una matriz de acciones, que, luego, se muestran al usuario.
const LOCAL_BASE_URL = 'http://localhost:7071';
const app = new Vue({
el: '#app',
interval: null,
data() {
return {
stocks: []
}
},
methods: {
async update() {
try {
const apiUrl = `${LOCAL_BASE_URL}/api/getStocks`;
const response = await axios.get(apiUrl);
app.stocks = response.data;
} catch (ex) {
console.error(ex);
}
},
startPoll() {
this.interval = setInterval(this.update, 5000);
}
},
created() {
this.update();
this.startPoll();
}
});
Una vez que el método startPoll
comienza el sondeo, se llama al método update
cada cinco segundos. Dentro del método update
, se envía una solicitud GET a la función getStocks
y el resultado se establece en app.stocks
, lo que actualiza la interfaz de usuario.
El código de cliente y servidor es relativamente sencillo, pero, como se descubre en nuestro análisis, esta simplicidad aporta algunas limitaciones.
Compatibilidad de CORS
En el archivo local.settings.json, la sección Host
incluye los siguientes valores.
"Host" : {
"LocalHttpPort": 7071,
"CORS": "http://localhost:8080",
"CORSCredentials": true
}
Esta configuración permite que una aplicación web que se ejecuta en localhost:8080 realice solicitudes a la aplicación de función que se ejecuta en localhost:7071. La propiedad CORSCredentials
indica a la aplicación de función que acepte las cookies de credencial de la solicitud.
CORS es una característica de HTTP que permite que una aplicación web que se ejecuta en un dominio tenga acceso a recursos de otro dominio. Los exploradores web implementan una restricción de seguridad denominada directiva del mismo origen que impide que una página web llame a las API de otro dominio diferente; CORS proporciona una forma segura de permitir que un dominio (el dominio de origen) llame a las API de otro dominio.
Puede establecer reglas CORS individualmente para cada uno de los servicios de Azure Storage. Para ello, llame a Set Blob Service Properties, Set File Service Properties, Set Queue Service Properties y Set Table Service Properties. Una vez establecidas las reglas de CORS para el servicio, una solicitud debidamente autorizada realizada contra el servicio desde un dominio diferente se permite o no según las reglas que haya especificado.
Análisis de la solución actual
Vamos a pensar en algunos de los inconvenientes de este enfoque de sondeo basado en temporizador.
En el prototipo de sondeo basado en temporizador, la aplicación cliente se pone en contacto con el servidor tanto si hay cambios en los datos subyacentes como si no. Cuando se devuelven datos desde el servidor, toda la lista de acciones se actualiza en la página web, una vez más, independientemente de los cambios en los datos. Este mecanismo de sondeo es una solución ineficaz.
La selección del mejor intervalo de sondeo para el escenario también supone un reto. El sondeo obliga a elegir entre el costo de cada llamada al back-end y la rapidez con la que se quiere que la aplicación responda a los nuevos datos. Los retrasos a menudo existen entre el momento en que los nuevos datos están disponibles y el momento en que la aplicación los detecta. En la ilustración siguiente se muestra el problema.
En el peor de los casos, el retraso potencial para detectar datos nuevos es igual que el intervalo de sondeo. Así que, ¿por qué no usar un intervalo menor?
A medida que la aplicación crece, la cantidad de datos intercambiada entre el cliente y el servidor se convierte en un problema. Cada encabezado de solicitud HTTP incluye cientos de bytes de datos junto con la cookie de la sesión. Toda esta sobrecarga, especialmente si hay una carga elevada, crea recursos desperdiciados y afecta innecesariamente al servidor.
Ahora que está más familiarizado con el punto inicial de la aplicación, es hora de hacer que la aplicación se ejecute en el equipo.