Este artículo forma parte de una serie de artículos sobre el diseño de soluciones de arquitectura.

En este artículo continuamos profundizando en el diseño de arquitectura, considerando aspectos más técnicos y cercanos al desarrollo.

Modelo técnico

El modelo técnico, como el modelo funcional, describe la estructura lógica de aplicaciones e integraciones, pero en este caso poniendo el foco en los detalles técnicos de implementación de los casos de uso.

Una forma sencilla de conseguir esta vista es copiar el modelo de arquitectura funcional, eliminar el detalle de las funcionalidades y entidades de datos que no sean relevantes desde un punto de vista técnico, e incluir las decisiones técnicas para implementar los casos de uso.

Desglosamos a continuación las aplicaciones en componentes técnicos, llegando al nivel de detalle de artefactos, para poder analizar la complejidad técnica de implementación y describir concisamente las decisiones técnicas sobre cada componente.

También añadimos los nuevos componentes técnicos necesarios para hacer que todos los casos de uso puedan funcionar de la forma más eficiente posible y aplicando las buenas prácticas de diseño de arquitectura, sobre todo a nivel de integraciones y almacenamiento, tales como middlewares de integración y almacenamiento de datos.

El contenido a detallar en el modelo podría ser el siguiente:

Caso práctico

Veamos un ejemplo de modelo técnico sobre nuestro caso.

Estructura de la arquitectura técnica del caso práctico

Al igual que en el modelo funcional, es recomendable explicar brevemente la nueva información para que se pueda entender fácilmente el diagrama y las decisiones técnicas clave. Las decisiones planteadas aquí son solo un ejemplo perfectamente discutible, sin otra intención de plantear qué tipo de decisiones son las que hay que resolver con este modelo.

El modelo no detalla las aplicaciones existentes que no tienen impacto. Hacerlo así pone el foco realmente en el alcance del proyecto aunque no dé una visión completa del sistema.

También podemos identificar los principales errores técnicos que se pueden producir en cada elemento o integración de la arquitectura para describir cómo deberían gestionarse desde el punto de vista de arquitectura.

El contexto del caso práctico que estamos abordando es el siguiente:

La aplicación de servicios de RRHH es la aplicación existente para la gestión manual de preferencias de guardias, que evolucionaremos para implementar las nuevas funcionalidades y mejoras.

Actualmente, esta aplicación es un monolito con una interfaz de usuario anticuada. Dado que hay que rediseñar la interfaz, se aprovechará para separarla en una aplicación web (que será nueva) y una capa de servicios, aprovechando la mayor parte de la aplicación actual. Para la nueva web app, tras algunas revisiones, se vio que la mejor opción era optar por React al tener un equipo de soporte del cliente con conocimientos y ser una tecnología conocida en el mercado. La capa de servicios se mantendrá en las tecnologías actuales.

Para el consumo de los servicios se plantea utilizar un API Gateway que permita abstraer ambas capas, así como soportar la seguridad y monitorización del uso de los servicios. Además, la aplicación actual de gestión de empleados proporciona sus servicios mediante WS SOAP. Para homogeneizar el consumo de servicios también se publicarán en el API Gateway como APIs REST y los servicios de “Servicios de RRHH” los invocarán a través del API Gateway.

Actualmente no existe un API Gateway, por lo que se realizó un análisis de alternativas con los especialistas que dan soporte al diseño y se optó por la implantación de Mulesoft Anypoint (en un caso real se enlazaría este análisis, pero por acotar el contenido del artículo al diseño lo omito).

Para la implementación de las integraciones asíncronas que responden a los eventos identificados se propone utilizar un Broker de eventos, que tampoco existe en el hospital. De forma similar, se realizó un análisis y se optó por la implantación de Azure Event Grid. Para esta decisión fue clave considerar que la estrategia de implementación de nuevas aplicaciones sería sobre Azure. Esta decisión no fue del perfil de arquitectura de soluciones, sino que se tomó escalando la necesidad a la dirección en los foros de estrategia de TI.

De forma alineada con esta estrategia, la nueva aplicación “Gestor de notificaciones” se plantea implementarla como un servicio en Azure Functions que permite realizar el despliegue de forma muy ágil, escalar dinámicamente y tiene un coste muy pequeño con baja volumetría, como vimos en los requisitos no funcionales. Para la gestión de las plantillas y tipos de notificación, el servicio utilizará una base de datos relacional en Azure SQL.

El planificador de procesos periódicos ya existe actualmente, por lo que solo hay que configurar los nuevos eventos como planificaciones. Para lanzar el servicio, el planificador puede invocarlo como API, pero se trata de un servicio muy pesado que puede llegar a durar horas, como se indica en los requisitos no funcionales. Para evitar esta situación, el lanzamiento del proceso lo realizará a través del broker de eventos, con la contraprestación de que no podrá obtener como respuesta el resultado de su ejecución.

En el modelo funcional del artículo anterior teníamos la intuición de que el servicio de planificación podría ser muy pesado. Al revisarlo con el equipo de desarrollo observamos que el algoritmo a utilizar tiene una complejidad de O(n²D), donde n es el número de personas sanitarias y D el número de días del mes a planificar. Con 1000 personas en un mes promedio de 30 días y un tiempo de operación de 1ms, aplicando diferentes reglas de validación sobre cada posibilidad, el tiempo estimado podría rondar un promedio de unas 8 horas con bastante margen de error (es solo una estimación teórica, pero nos da una idea).

Considerando estos datos, estimamos que con esta solución no podríamos cumplir los requisitos no funcionales de tiempo que teníamos inicialmente. El primer impulso de un perfil técnico podría ser tratar de optimizar el desarrollo e incluir cálculo paralelo, lo que nos podría llevar a la necesidad de implementar clusters de servidores u otras complejidades técnicas.

Pero, tras hablar con negocio para entender mejor la necesidad de estos cálculos y analizar una mejora de eficiencia del algoritmo, se pudo ver que la planificación se hace por departamentos, que son unos 20 departamentos de unas 50 personas en cada uno de promedio. Esto descarta todas las posibilidades de interacciones entre departamentos. Aplicando el mismo algoritmo por departamentos, nos encontramos con que la complejidad es la misma, pero el volumen de datos a trabajar en cada ejecución es mucho menor, quedando un tiempo estimado de ejecución de alrededor de 25 minutos.

El ejemplo está planteado para ilustrar que, en muchas ocasiones, tratamos de paliar problemas funcionales con soluciones técnicas y nos complicamos la vida. Tengamos siempre la vista puesta en optimizar el diseño funcional antes de pasar a las decisiones técnicas.

También nos sirve para ilustrar casos en los que este tipo de análisis nos pueden ayudar a prevenir los problemas y desarrollos complejos y costosos, ya sea porque estos tiempos de ejecución no se observan hasta que los desarrollos están hechos en entornos previos, porque se improvisan soluciones técnicas para salir del paso o ni siquiera se tienen los requisitos no funcionales y el problema se detecta en producción.

La implantación del API Manager y el Broker de eventos ha sido un imprevisto para el cliente que plantea posibles retrasos y costes adicionales en el proyecto pero, tras debatirlo, se decidió que era la mejor opción con la previsión de la implantación de nuevas aplicaciones y servicios que podrán aprovechar las nuevas plataformas, por lo que aceptaron el cambio. Gracias al uso de un diseño de solución, esta cuestión se ha analizado en un momento apropiado en el que los cambios tienen poco impacto en el proyecto y, sobre todo, se ha orientado la implementación hacia la creación de bases estratégicas para la evolución de las aplicaciones.

En el caso de errores técnicos o timeouts de los servicios, la web app ha incluido en su diseño técnico animaciones y páginas de error específicas que se han podido revisar con UX y seguridad en fase de diseño.

El proceso de planificación de turnos, en el caso de que se produzcan errores en los servicios de consulta de datos, implementará una política de reintentos espaciados cada 30 segundos acumulativos, hasta 5 veces. En el caso de agotar los reintentos o por cualquier otro error que impida la ejecución del proceso, se cancelará y enviará un evento de error en el proceso de planificación de turnos. Al revisar esta situación, se ha visto la necesidad de implementar un nuevo servicio en la aplicación “Servicios de RRHH” para gestionar este evento y enviar una nueva notificación al administrador de sistemas.

Cuando tengamos un modelo aterrizado, hacemos otra iteración para revisar que la arquitectura planteada cumple con los principios de arquitectura, la arquitectura de referencia y los patrones de diseño de arquitectura, en este caso más orientada a alinear la solución con la estrategia tecnológica.

Para el diseño de la arquitectura técnica, es importante validar que es viable, considerando si las tecnologías o productos a utilizar son adecuados para el tipo de funcionalidad, si soportan los tipo de integración, si permiten personalizarse como se necesitaría, si pueden escalar para los escenarios planteados, si los tipos de integración son los más adecuados, si los tipos de almacenamiento son los más adecuados, si es demasiado compleja, costosa o larga de implementar… debemos cuestionar cada detalle del diseño.

En nuestro caso práctico, la solución de lanzar los procesos planificados mediante eventos del broker nos ha conducido a tener que implementar un servicio específico para gestionar los errores en el cálculo de la planificación de turnos, lo que no parece una solución óptima.

Podemos refinar este punto con soluciones alternativas, como utilizar un script para invocar al servicio con un timeout suficientemente alto y que espere el tiempo necesario o, directamente, implementar el proceso como un proceso batch en un componente diferente del back de servicios. Vamos a decantarnos por esta última opción ya que, por principios de diseño, para implementar procesos batch planificados mejor utilicemos tecnologías de procesamiento batch.

Estructura de la arquitectura técnica de nuestro caso práctico

Integraciones

Para detallar las integraciones podemos utilizar una tabla como esta:

IDI Descripción Autenticación / autorización Tamaño de datos
ID Integration description Tipo de autenticación y control de acceso Tamaño de datos del interfaz

IDI sería el identificador de la integración. Este identificador nos permite trazar las integraciones del diagrama con la tabla y referenciarlas en la explicación.

Es de especial interés revisar el tamaño de los datos en las integraciones. En combinación con las volumetrías de peticiones, permitirá evaluar si el tipo de integración o si el tipo de tecnología para implementar los componentes que procesan estos datos son los más adecuados. Este tamaño probablemente no podremos saberlo con exactitud en el momento del diseño de arquitectura, pero una aproximación de orden de magnitud estimada sobre los campos aproximados de las entidades que se comunican deberían ser suficiente para entender al problema que nos enfrentamos y si es relevante o no. Se trata de cuantificar en órdenes de magnitud e identificar si los datos tienen tamaños de KBs, MBs o GBs.

En proyectos que tengan requisitos altos de volumetría de operaciones en los que se reutilizan servicios o hay componentes comunes, sería recomendable incluir en la tabla de integraciones un campo para indicar una volumetría estimada de peticiones, en base a las volumetrías de los casos de uso. La podemos calcular como el sumatorio de las peticiones de todos los casos de uso sobre esa integración.

Este cálculo nos permite revisar si hay cuellos de botella que concentran las peticiones. Si disponemos de datos de pruebas de estrés realizadas sobre los componentes, podemos comprobar si el incremento de volumetrías planteado por el proyecto excede las capacidades actuales. Es el momento perfecto para realizar POCs y realizar las pruebas de estrés si tenemos incertidumbres sobre la capacidad del diseño.

Finalmente, podemos indicar qué tipo de autenticación y autorización se necesita en cada integración. Esto permitirá gestionar fácilmente al equipo, certificados y configuraciones necesarias y tenerlo en cuenta en los desarrollos de las llamadas a servicios o escrituras de ficheros.

Caso práctico

IDI Descripción Autenticación / autorización Tamaño de datos
1 La app web de Servicios de RRHH invoca a los servicios publicados en el API Gateway para gestionar sus funcionalidades OpenID / OAuth2 <10KB
2 El API Gateway invoca a los servicios de "App back Servicios de RRHH" para orquestar las respuestas a las APis de gestión de servicios de RRHH. OpenID / OAuth2 <10KB
3 Los servicios de "App back Servicios de RRHH" gestionan los datos de preferencias de guardias, planificación de turnos y cambios de turnos en la BD "Servicios de RRHH". Username/Password - LDAP <10KB
4 El proceso de planificación de turnos consulta invoca las APIs de gestión de empleados para consultar el calendario laboral y los datos de los empleados. OpenID / OAuth2 100KB - 10 MB
5 El API Gateway invoca a los servicios de "App gestión de empleados" para orquestar las respuestas a las APis de consulta de datos de empleados y calendario laboral SAML2 100KB - 10 MB
6 El proceso de planificación de turnos gestiona los datos de preferencias de guardias y planificación de turnos en la BD "Servicios de RRHH" Username/Password - LDAP <10KB
7 Los servicios de "App back Servicios de RRHH" publican en el broker de eventos los eventos asociados a los flujos de operaciones y notificaciones. SAS/OAUTHBEARER <10KB
8 El proceso de planificación de turnos publican en el broker de eventos que está disponible. SASL/OAUTHBEARER <10KB
9 El servicio de envío de notificaciones consume los eventos que conllevan envio de notificaciones del broker de eventos SASL/OAUTHBEARER <10KB
10 El servicio de envío de notificaciones consulta los tipos de notificación y sus plantillas para conformar los mensajes OpenID / OAuth2 <10KB

Los protocolos a utilizar serán los nuevos estándares establecidos para la integración mediante APIs por REST/HTTP y eventos con Kafka, pero mantendremos los protocolos actuales para los componentes que no tienen impacto.

Para la autenticación / autorización se plantea el uso de OpenID/Oauth2, pero no disponen de un IDP compatible. Actualmente utilizan un LDAP y un IDP a medida que soporta SAML2. Se escala la cuestión a la dirección y se decide que en sinergia con la evolución en Azure se utiliza Azure AD, que soporta los nuevos protocolos, federado con el LDAP y se migre el actual IDP. Esto es un nuevo imprevisto para el cliente que plantea posibles retrasos y costes adicionales en el proyecto, pero que se ha podido detectar a tiempo en el diseño.

Revisando los tamaños de datos, observamos que los datos de contratos de los empleados tienen un tamaño considerable para ser gestionado por el API, ya que se trata de consultar un número muy alto de empleados, por lo que se plantea implementar paginación en el API de consulta de datos de empleados. Dado que el número de consultas no es muy alto, no se plantean medidas adicionales.

Despliegue

La vista de despliegue se centra en los artefactos de software y los requisitos que tienen para funcionar en los entornos. Los datos propuestos a definir son los siguientes:

Componentes de aplicación

Componente de aplicación # Usuarios totales # Usuarios concurrentes Tamaño de almacenamiento Disponibilidad
Nombre del componente Número de usuarios totales Número de usuarios concurrentes Almacenamiento necesario para desplegar el componente Disponibilidad según requisitos по funcionales

Software base

Producto Versión Proveedor Licenciamiento
Nombre del componente del producto Versión del producto Proveedor del producto Número y tipo de licencias necesarias

Servicios cloud

Servicio Plataforma Proveedor Licenciamiento
Nombre del servicio cloud Plataforma que proporciona el servicio Proveedor del servicio Número y tipo de licencias necesarias

Logs

Componente de aplicación Tipo de logs Almacenam. de logs Ruta de los logs Tamaño de almacenam. Políticas de rotación Eventos de seguridad
Componente que genera los logs Servicio que genera los logs Tipo de almacenamiento Ruta de los logs Tamaño de los logs acumulados Políticas de limpieza de logs Identificar si hay logs a registrar en SIEM

Estos datos pueden calcularse a partir de los requisitos no funcionales y las volumetrías de los casos de uso, aplicándolos a los componentes, integraciones y tamaños de datos.

Hay que tener en cuenta que los casos de uso o procesos suelen ser transversales a varias aplicaciones y componentes y viceversa, los componentes suelen dar servicio a varios casos de uso o procesos. La criticidad de un componente es la misma que la del proceso más crítico al que da servicio. Esta cuestión es importante de cara a definir los requisitos de disponibilidad, robustez y recuperación de los componentes.

Las licencias de software base y servicios cloud son relevantes sobre todo para estimar el coste de la arquitectura.

La arquitectura, en principio, no detalla cuestiones como la configuración del software, pero no se puede descartar que esta configuración pueda ser relevante desde el punto de vista de arquitectura en algún caso. Esto dependerá del software a desplegar y el equipo de arquitectura podrá incluirlo en esta sección a demanda. Si pensamos en la configuración de servidores y servicios, en el próximo artículo veremos cómo detallarla como parte del diseño de infraestructura.

Podemos definir también la arquitectura de desarrollo necesaria para gestionar el ciclo de vida del software, aunque normalmente ya existe y los proyectos se gestionan de la forma ya establecida, por lo que el diseño suele limitarse a definir los proyectos y circuitos de desarrollo y despliegue que se necesitan crear. En mi opinión, no es objeto del diseño de arquitectura detallar estos circuitos salvo que se identifiquen necesidades específicas de los componentes a desplegar o las pruebas a realizar.

Además de desplegar los artefactos, se deben considerar las necesidades de datos para que las aplicaciones funcionen correctamente. Esto incluye cargas de tablas con datos maestros, cargas iniciales de datos operacionales y migraciones de datos y archivos de aplicaciones actuales.

Desde la perspectiva de la arquitectura, las soluciones deben abordar:

Es crucial centrarse en los datos necesarios para la nueva arquitectura en lugar de qué hacer con los datos existentes. Puede ser necesario "componer" nuevos datos de otras fuentes, además de los sistemas origen, o puede haber datos que ya no sean necesarios debido a la obsolescencia de los procesos.

Además, se debe considerar si hay datos que no se necesitan en las aplicaciones operacionales, pero que deben conservarse por requisitos legales o de negocio. Estos podrían gestionarse en almacenamiento barato o podríamos revisar si ya se encuentran en los sistemas informacionales.

En ocasiones, los procesos de migración requieren su propia arquitectura aunque sea efímera.

Caso práctico

Componente de aplicación # Usuarios totales # Usuarios concurrentes Tamaño de almacenamiento Disponibilidad
App web Servicios de RRHH 1000 50 100MB 24x7, 99%
App back Servicios de RRHH N/A N/A 100MB 24x7, 99%
App batch Servicios de RRHH N/A N/A 100MB Noches de días 15, 20 y 25 mensuales
API Gateway N/A N/A 1GB 24x7, 99'9%
Event broker N/A N/A 1GB 24x7, 99'9%
Gestor de notificaciones N/A N/A 100MB 24x7, 99%

Hemos validado con negocio que el número de sanitarios del hospital son unos 1000 usuarios, de los cuales puede haber a la vez unos 50. El espacio de almacenamiento de los componentes lo estimamos en base al tipo de tecnología que se va a desplegar. La disponibilidad de los componentes la estimamos considerando los requisitos no funcionales de los casos de uso que tienen que implementar. En este caso, debido a que puede llegar a tener caídas de hasta 24 horas, estimamos que con un 99% de disponibilidad es suficiente.

Software base

Producto Proveedor Licenciamiento
Kubernetes Paradigma Digital Open Source
Chrome Google Freeware
Edge Microsoft Freeware

Servicios cloud

Servicio Plataforma Proveedor Licenciamiento
EventGrid Azure Microsoft Basic Tier
Functions Azure Microsoft On Demand
SQL Database Azure Microsoft Serie Estándar (Gen 5)
Active Directory Azure Microsoft Incluido en Office 365
Anypoint Platform Mulesoft Salesforce Integration starter

En cuanto a software base, solo vamos a necesitar para desplegar un cluster de Kubernetes, para la web app, los servicios y batch. El resto de componentes se desplegarán sobre servicios cloud de Azure o Salesforce en su versión de licenciamiento más baja, ya que el volumen de operaciones estimadas a realizar tendrán costes gratuitos o muy bajos y los requisitos no funcionales quedan cubiertos con estos servicios. Sí hay que tener en cuenta la necesidad de contratar el servicio de Azure para el hospital.
La nueva web debe ser compatible con las últimas versiones de los navegadores Chrome y Edge, tanto en dispositivos móviles como PC. Se descarta de momento su uso en dispositivos Apple.

Hay que considerar que aquí no detallamos el software incluido en los artefactos a desplegar tales como librerías o frameworks de desarrollo.

Logs

Componente de aplicación Tipo de logs Almacenam. de logs Ruta de los logs Políticas de rotación Eventos de seguridad
App web Servicios de RRHH log4j 1 GB Ruta en la NAS 7 días N/A
App back Servicios de RRHH log4j 1 GB Ruta en la NAS 7 dias N/A
API Gateway Anypoint logs 2 GB Ruta en la NAS 7 días Registro de llamadas a servicios, Errores de acceso
Event broker Kafka logs 2 GB Azure Monitor 7 días N/A
Gestor de notificaciones log4j 1GB Azure Monitor 7 días Notificaciones enviadas

En cuanto a los logs, hacemos una estimación de tamaño al que pueden llegar con una política de rotación de 7 días. No tiene que ser exacto y se puede ajustar después, pero permite identificar ya la necesidad de reservar estos recursos. Finalmente, identificamos algunos logs del API Manager y el envío de notificaciones que pueden ser de interés para seguridad.

Desde el punto de vista de seguridad, podemos identificar ya los usuarios personales y técnicos necesarios para realizar el despliegue de los componentes, así como los grupos, roles y permisos necesarios a configurar para las aplicaciones, políticas de acceso, certificados o cualquier otro elemento de seguridad que se necesite desplegar.

Caso práctico

Siguiendo con nuestro caso práctico, la aplicación de “Servicios de RRHH” tendrá 2 roles de usuario: “Gestor” y “Sanitario”. Para gestionarlos, definiremos en el IDP los roles correspondientes. Todos los usuarios de los empleados del hospital tendrán asignados uno de los roles. El control de acceso a las funcionalidades según el rol lo implementará la “App de servicios de RRHH”.

Las APIs también implementarán control de acceso. Para ello, se configurarán como recursos en el IDP con control de acceso RBAC y el API Manager controlará el acceso a las APIs según el usuario autenticado en las peticiones delegando la validación en el IDP.

El resto de APIs y eventos se autentican y controlan el acceso con usuarios técnicos de servicios. Para ello, se necesita crear los siguientes usuarios técnicos en el IDP y los correspondientes certificados que se instalarán en el despliegue de los componentes:

Estos usuarios tendrán permisos para acceder a los servicios y recursos como se indica en el diseño de arquitectura (si es necesario, se pueden enumerar).

La autenticación de los usuarios se basará en acceso con usuario y contraseña. Se recomendó el uso de 2º factor de autenticación pero se decidió implementarlo en una fase posterior.

No suele ser imprescindible definir esta vista en las primeras iteraciones del modelo de solución, sobre todo en fases tempranas de conceptualización de los proyectos. Pero si se requieren realizar POCs o el equipo funciona con entregas rápidas desde el principio, es importante considerarlo y trabajarlo desde las primeras iteraciones en que la arquitectura técnica esté aterrizada.

Esta vista generalmente se trabaja con el apoyo del equipo de desarrollo y arquitectura de software. La labor del rol de arquitectura de soluciones es gestionar esta información como apoyo al equipo.

Además, esta información es relevante para analizar y entender mejor los requisitos de infraestructura para el proyecto.

Conclusión

En este artículo hemos visto cómo evolucionar el modelo funcional a un modelo técnico que proporcione la visión del proyecto en un lenguaje más cercano al equipo de desarrollo y equipos técnicos.

En el próximo capítulo veremos cómo completar el modelo de solución con la visión de infraestructura.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete