GithubHelp home page GithubHelp logo

alejovillores / arquitectura-2c23-tp-1 Goto Github PK

View Code? Open in Web Editor NEW

This project forked from saantim/2c23-tp-1

0.0 0.0 0.0 2.56 MB

Trabajo Práctico 1 del 2do cuatrimestre de 2023

Shell 1.06% JavaScript 96.51% Dockerfile 2.42%

arquitectura-2c23-tp-1's Introduction

Punto de partida para el TP 1 de Arquitectura del Software (75.73) del 2do cuatrimestre de 2023

La fecha de entrega para el informe y el código es el jueves 05/10 ‼️

La forma de entrega será a través del canal de Slack del grupo. Deben poner ahí un link al repositorio con el código (en caso de ser privado, invitar también a los docentes) y el informe (o avisar si está en el repositorio).

El informe puede ser un PDF, Google Doc o Markdown/Wiki en el mismo repositorio del código. Debe incluir screenshots del dashboard de métricas para cada caso analizado que permitan observar los resultados obtenidos y debe incluir una vista Components & Connectors para los distintos casos estudiados.

Objetivos

El objetivo principal es comparar algunas tecnologías, ver cómo diversos aspectos impactan en los atributos de calidad y probar qué cambios se podrían hacer para mejorarlos. El objetivo menor es que aprendan a usar una variedad de tecnologías útiles y muy usadas hoy en día, incluyendo:

  • Node.js (+ Express)
  • Docker
  • Docker Compose
  • Nginx
  • Redis
  • Algún generador de carga (la propuesta es usar Artillery, pero pueden cambiarlo)
  • Alguna forma de tomar mediciones varias y visualizarlas, preferentemente en tiempo real, con persistencia, y en un dashboard unificado (la propuesta es usar el plugin de Artillery + cAdvisor + StatsD + Graphite + Grafana, pero pueden cambiarlo).

Consigna

Implementar un servicio HTTP en Node.js-Express que represente una API que consume otras APIs para dar información a sus usuarios, similar a lo que brindaría una API para una página de inicio personalizada. Someter sus endpoints a diversas intensidades/escenarios de carga en algunas configuraciones de deployment, tomar mediciones y analizar resultados.

A partir de este repositorio como punto inicial, van a tener que implementar el webserver y dockerizarlo (completar la carpeta app/), agregar los servicios con el webserver al docker-compose.yml, y configurar las locations y upstreams de nginx en nginx_reverse_proxy.conf.

El tráfico entre cliente y servidor debe pasar por el nginx, para que tenga la latencia del salto "extra"

Para generar carga y ver las mediciones obtenidas, en la carpeta perf/ tienen un dashboard de Grafana ya armado (dashboard.json) al que deberán ajustar según las características de su equipo de pruebas (RAM, cores) y un ejemplo de un escenario básico de Artillery (deben crear sus propios escenarios de manera apropiada para lo que estén probando). También hay un script y una configuración en el package.json para que puedan ejecutar los escenarios que hagan corriendo:

npm run scenario <filename> <env>

donde <filename> es el nombre del archivo con el escenario (sin la extensión .yaml) y <env> es el entorno en el cual correrá la prueba (vean la sección environments dentro del yaml del escenario).

Servicios

Ping

Endpoint: /ping

Este servicio devolverá un valor constante, sin procesamiento. Lo utilizaremos como healthcheck y como baseline para comparar con los demás.

METAR

Endpoint: /metar?station=<code>

Ejemplo: /metar?station=SAEZ (para el Aeropuerto de Ezeiza)

Un METAR es un reporte del estado meteorológico que se registra en un aeródromo. Se lo codifica en un string, por ejemplo:

KDEW 111218Z AUTO 20010KT 10SM -RA SCT012 BKN020 OVC033 06/05 A2981 RMK AO2 P0002 T00610050

Interpretación de algunos campos:

  • KDEW: Código del aeródromo (Deer Park Airport)
  • 20010KT: Viento de 10 nudos desde la dirección 200
  • 10SM: Visibilidad de 10 millas
  • -RA: Lluvia leve
  • SCT012: Nubes dispersas a 1200 pies
  • BKN020: Parcialmente nublado a 2000 pies
  • OVC033: Cubierto a 3300 pies
  • T00610050: Temperatura de 6,1 grados y punto de rocío de 5 grados

Nuestro servicio recibirá un código OACI de un aeródromo y delegará la consulta a la NOAA Text Data Server API (ver ejemplos). Solicitaremos la información en formato XML y la convertiremos a JSON para entregarla a nuestro cliente. Podemos hacerlo así:

//Importamos los componentes necesarios
const axios = require('axios');
const { XMLParser } = require('fast-xml-parser');
const { decode } = require('metar-decoder');

const parser = new XMLParser();

...

//Consultamos a la API de NOAA
const response = await axios.get(`https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&stationString=${station}&hoursBeforeNow=1`);
//Convertimos el XML obtenido a JSON, por conveniencia
const parsed = parser.parse(response.data);
//Decodificamos el METAR
decode(parsed.response.data.METAR.raw_text);

Importante: El ejemplo anterior es solo una manera de hacerlo, pueden utilizar la que prefieran. No se están contemplando situaciones de error (METAR vuelve vacío, error de conexión a NOAA, error de parseo, etc.), que sí deberían ser contempladas por ustedes, devolviendo un error apropiado al cliente.

Spaceflight News

Endpoint: /spaceflight_news

Devolveremos solo los títulos de las 5 últimas noticias sobre actividad espacial, obtenidas desde la Spaceflight News API.

Ver documentación de la API

Random quote

Endpoint: /quote

Devolveremos 1 cita famosa con su autor (ningún otro dato) al azar por cada invocación, tomada de Quotable. Debe evitarse entregar la misma cita cada vez (salvo que la repita la API remota).

APIs opcionales

Pueden agregar más endpoints que consulten a otras APIs. Para buscar APIs que sean gratuitas y de uso público, pueden consultar aquí.

Importante: Es preferible hacer un buen análisis de lo obligatorio en vez de agregar más APIs con un análisis superficial. Solo agreguen opcionales si terminaron de manera consistente con lo obligatorio, siendo también consistentes con lo que agreguen.

Tácticas

Caso base

El caso base existe solo para tomar como referencia y poder verificar si hay mejoras con las tácticas aplicadas.

Caché

Utilizarán Redis como caché (ver redis)

La idea es que elijan la estrategia más apropiada para llenar, conservar y vaciar la información del caché según estos criterios (consulten la documentación tanto de las APIs como de aquello que informan para poder contestar las siguientes preguntas):

  • Aplicación: Esta información, ¿es cacheable?
  • Tamaño: Cuántos ítems almacenar en el caché.
  • Llenado: Decidir entre
    • Active population: Incorporar la información al caché antes de que la solicite el cliente.
      • ¿Se puede traer información cada cierto tiempo para tener algo que darle al cliente?
    • Lazy population: Incorporar la información cuando la pide el primer cliente.
  • Tiempo de vida: Cuánto tiempo debe permanecer el dato en el caché antes de ser eliminado. Depende de si la información que almacenamos expira (deja de tener validez por paso del tiempo) o puede estar permanentemente / hasta ser accedida por alguien.
  • Vaciado: Si tomo un ítem del caché, ¿debo eliminarlo o puede/debe permanecer para otro pedido?

Replicación

Escalarán el servicio a 3 copias, convirtiendo a nginx en un load balancer.

Rate limiting

Deberán experimentar con una solución que limite el rate de consumo de la API. Pueden ver express-rate-limit o cómo hacerlo con nginx. No es necesario que prueben ambas, alcanza con una.

Tácticas opcionales

Pueden probar otras tácticas, pero recuerden que es mejor ser consistentes con lo que entregan y que no se puede cambiar algo obligatorio por algo opcional.

Generación de carga para las pruebas

Importante: Generen valores de carga que tengan relación con los tiempos que ven en la aplicación. No agrega valor que generen una carga enorme y luego cueste saber cuál de todos los componentes está fallando. Vayan de a poco con la carga y verifiquen cómo se van afectando los atributos de calidad. Analicen cada endpoint por separado. Si generan escenarios que los recorren juntos costará determinar dónde optimizar.

Hay muchos tipos de escenarios de carga y pruebas de performance en general. Pueden leer por ejemplo aquí (o en cualquiera de los miles de links al googlear sobre el tema) sobre algunos tipos de escenarios que pueden implementar. Queda a decisión de cada grupo elegirlos, considerando siempre cuál es el que más útil les resulta para analizar lo que quieran estudiar.

Tengan en cuenta que, en el caso de los METARs, la carga generada debe enviar distintos códigos de aeródromo cuando simulen los pedidos de los clientes. Vean formas de hacerlo aquí y aquí.

Métricas propias

Deberán generar las siguientes métricas, que se agregarán como gráficos adicionales a los que les damos en el dashboard:

  • Demora de cada endpoint en responder (esto es, API remota + procesamiento propio)
  • Demora de cada API remota en responder (solo API remota)

Pueden usar hot-shots

Aclaraciones sobre la entrega

  1. El trabajo debe entregarse completo. No se aceptan entregas parciales.
  2. Asumimos que todo el grupo participa en la resolución del trabajo. De ocurrir problemas o surgir contratiempos, es el grupo quien debe responder y solucionarlos. Pueden consultar a los docentes pero deben demostrar primero que intentaron solucionarlos internamente.
  3. De haber defectos importantes en el desarrollo o en el informe del TP, se solicitará una re-entrega. Esto tiene un impacto considerable en la nota final, por lo que les recomendamos que controlen entre todo el grupo el cumplimiento del enunciado, las conclusiones y las justificaciones antes de entregar el trabajo.

Links útiles

Pequeño cheatsheet de docker

Es posible que necesiten ejecutar los comandos con sudo, según el sistema que usen y cómo lo hayan instalado.

# Ver qué containers existen
docker ps [-a]

# Ver qué imagenes hay en mi máquina
docker images

# Ver uso de recursos de containers (como "top" en linux)
# Ejemplo con formato específico: docker stats --format '{{.Name}}\t{{.ID}}\t{{.CPUPerc}}\t{{.MemUsage}}'
docker stats [--format <format_string>]

# Descargar una imagen
docker pull <image>[:<tag>]

# Eliminar un container
docker rm <container_id> [-f]

# Eliminar una imagen
docker rmi <image_id> [-f]

# Eliminar imágenes "colgadas" (dangling)
docker rmi $(docker images -q -f dangling=true)

# Versión instalada
docker version

Pequeño cheatsheet de docker-compose

Todos los siguientes comandos deben ejecutarse desde la carpeta en donde está el archivo docker-compose.yml del proyecto.

Es posible que necesiten ejecutar los comandos con sudo, según el sistema que usen y cómo lo hayan instalado.

# ALIAS para escribir menos
alias docc='docker-compose'

# Ayuda general
docc --help

# Ayuda genral para cualquier comando
docc [COMMAND] --help

# Levantar servicios.
# Sugerencia: Usar la opción -d para levantar en background, y poder seguir usando la terminal
# También sirve para escalar horizontalmente un servicio que ya se esté ejecutando [buscar opción --scale].
# Si no se especifica al menos un servicio, se levantan todos
docc up [options] [SERVICE...]

# Ver logs de un servicio ejecutándose en background
docc logs [options] [SERVICE]

# Listar containers y sus estados
docc ps

# Restartear servicios
# Si no se indica al menos un servicio, se restartean todos
docc restart [SERVICE...]

# Frenar servicios corriendo en background (con la opción --detach del `up`)
# Si no se lista ningún servicio, se frenan todos.
# Esto solo frena servicio, no borra el container ni los datos que hayan en el mismo
docc stop [SERVICE...]

# Frenar containers y borrar tanto los containers como las imágenes y los volúmenes de almacenamiento
# (se pierden todos los datos que hubiera en el container).
# Esto aplica a TODOS los levantados con `up`, no filtra por servicio
docc down

# Levantar un nuevo container de un servicio y ejecutar un comando adentro
# (util para tener por ejemplo una terminal dentro de un container e inspeccionarlo o hacer pruebas manuales).
# Como es siempre sobre un container nuevo, lo que ven es el resultado de su docker-compose.yml y sus dockerfiles
# Ejemplo: docc run graphite bash
docc run SERVICE COMMAND

# Correr un comando en un container que ya existe y ya está corriendo.
# Parecido a `run` pero sobre un container en ejecución.
# Útil para alterar o inspeccionar algo que se está ejecutando.
#Lo que ven adentro puede no ser el resultado directo del docker-compose.yml + dockerfiles, así que mucho cuidado
# si van a modificar sus containers así, porque puede ser difícil de reproducir luego.
# Ejemplo: docc exec graphite bash
docc exec SERVICE COMMAND

# Versión instalada
docc version

Devolucion y Correcciones

Devolución de TP 1 - On Clouds - NOTA 6

  • Aparece muchas veces la palabra “estrategia” para referirse a “táctica”. Estos dos conceptos son distintos e importantes en el contexto de esta materia.
  • En el caso base NGINX no funciona como “load balancer” sino como “reverse proxy”.
  • Falta la justificación de la elección de tiempos de vida en el caché. Veo en la configuración que seleccionaron 5 segundos para Spaceflight News y 1 hora para METAR, ¿cómo sería el razonamiento para llegar a esos números?
  • Como comentario sin impacto en la nota, revisen la documentación de Redis para ver el parámetro EX, que les permite descargar en la herramienta el manejo del tiempo de expiración de las entries.
  • NGINX devuelve 503 por default cuando aplica rate limiting. Si quieren que devuelva otro código, como 429, tienen que especificarlo.
  • Falta análisis de rate limiting y justificación del límite seleccionado.
  • Con respecto a la medición de tiempos de respuesta del servicio vs. API externa, el caso base es una referencia pero falta ver el impacto de las tácticas, sobre todo la táctica de caching. Es importante determinar si alguna táctica desacopla la demora local versus la demora remota.

arquitectura-2c23-tp-1's People

Contributors

celedituro avatar alejovillores avatar mateocapon avatar joaqogomez avatar mdascan avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.