¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.dev
Yavé Guadaño Ibáñez 04/10/2023 Cargando comentarios…
En la actualidad tecnológica, donde el desarrollo de software viene marcado por sistemas distribuidos y en general implementados en microservicios, la adopción de patrones y diseños para soluciones genéricas parece casi una necesidad. Estos patrones solucionan temas comunes, como la migración de un monolito a microservicios, la convivencia de un sistema legacy con uno actual, la puesta en producción, las comunicaciones, la resiliencia, la escalabilidad, etc.
Por eso, hoy empezamos una serie de posts para hablar de la arquitectura de microservicios:
Los patrones de arquitectura de microservicios ofrecen una serie de beneficios y ventajas para el diseño y desarrollo de aplicaciones. Estos patrones están diseñados para abordar los desafíos específicos que surgen al construir sistemas basados en microservicios.
A continuación, os proponemos una serie de post que nos vayan guiando por los diferentes patrones que resuelven todos estos casos. La idea es crear una visión intermedia donde quede claro en qué consiste cada uno de los puntos (sin entrar demasiado en detalle porque sería tan extenso que daría para escribir un libro). En otros posts paradigmáticos ya hablábamos de los patrones más orientados al desarrollo de software, así como las 5 reglas del diseño de software simple y los principios SOLID.
Hoy nos vamos a centrar en los patrones de arquitectura enfocados a la organización y estructura de microservicios.
La arquitectura de microservicios es un enfoque moderno y flexible para el diseño de aplicaciones. En lugar de construir una sola aplicación monolítica, la descomponemos en pequeños servicios independientes. Cada servicio se centra en una tarea específica y se comunica con otros servicios a través de interfaces bien definidas.
La idea es que cada microservicio sea como una pieza de lego que encaje perfectamente en el rompecabezas de la aplicación completa. Cada servicio puede ser desarrollado, probado, desplegado y escalado de forma independiente, lo que facilita la agilidad y la entrega continua de software.
Un microservicio puede usar su propia tecnología y lenguaje de programación, lo que nos brinda la libertad de elegir la mejor herramienta para cada tarea. Además, al tener servicios pequeños e independientes, podemos mejorar la escalabilidad y la disponibilidad del sistema, ya que cada servicio puede ser replicado según la demanda.
Sin embargo, también hay desafíos asociados con la arquitectura de microservicios. La complejidad de gestionar múltiples servicios, la comunicación entre ellos y la necesidad de establecer una infraestructura sólida para el monitoreo y la gestión son aspectos importantes a tener en cuenta en el Gobierno de los servicios.
En resumen, la arquitectura de microservicios es una excelente opción para construir aplicaciones modernas y escalables. Con una correcta planificación y diseño, podemos aprovechar al máximo los beneficios de esta arquitectura y ofrecer soluciones robustas y adaptables a los desafíos actuales del desarrollo de software.
A la hora de diseñar la arquitectura de una aplicación debemos tener en mente el roadmap y qué necesidades tendremos en el futuro. También, tener en cuenta los diferentes tipos de arquitecturas de microservicios y saber qué tipo de preguntas debes hacerte a la hora de implementarla.
Veamos un ejemplo de una arquitectura básica de microservicios muy sencilla. En función de las necesidades tendremos que hacer modificaciones.
Como se ve en el diagrama, tenemos varios elementos:
La arquitectura de microservicios permite la independencia y la escalabilidad de los servicios, por lo que cada caja en el diagrama representa un servicio autónomo que puede ser desarrollado, desplegado y escalado de forma independiente. Además, el API Gateway actúa como una fachada para los microservicios y ayuda a gestionar la comunicación entre los clientes y los servicios.
El patrón Modelo-Vista-Controlador (MVC) es uno de los patrones arquitectónicos más conocidos y ampliamente utilizados en el desarrollo de aplicaciones web y de escritorio. El MVC divide la aplicación en tres componentes principales: Modelo, Vista y Controlador. Cada componente tiene una función específica y está diseñado para mantener una separación clara de preocupaciones.
Componentes del MVC:
En una aplicación Spring, este sería un ejemplo:
Modelo:
package com.ecommerce.model;
public class Product {
private Long id;
private String name;
private double price;
// Getters y setters
}
package com.ecommerce.repository;
import com.ecommerce.model.Product;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Repository
public class ProductRepository {
private final Map<Long, Product> products = new HashMap<>();
public Product findById(Long id) {
return products.get(id);
}
public List<Product> findAll() {
return new ArrayList<>(products.values());
}
public void save(Product product) {
products.put(product.getId(), product);
}
}
Vista:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Detalles del Producto</title>
</head>
<body>
<h1>Detalles del Producto</h1>
Nombre: ${product.name}
Precio: ${product.price}
</body>
</html>
Controlador:
package com.ecommerce.controller;
import com.ecommerce.model.Product;
import com.ecommerce.repository.ProductRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Controller
public class ProductController {
private final ProductRepository productRepository;
public ProductController(ProductRepository productRepository) {
this.productRepository = productRepository;
}
@GetMapping("/product/{id}")
public String getProduct(@PathVariable Long id, Model model) {
Product product = productRepository.findById(id);
model.addAttribute("product", product);
return "product"; // Nombre de la vista (product.jsp)
}
}
En este ejemplo, el ProductRepository se encarga de almacenar y gestionar los productos. El ProductController se comunica con el repositorio para obtener los datos del producto y pasarlos a la vista.
Ten en cuenta que este es un ejemplo muy simple y que, en aplicaciones más complejas, es posible que utilices bases de datos reales en lugar de una estructura de datos en memoria
MVC es algo tradicional y está viéndose sustituido por arquitecturas más modernas y más versátiles donde el frontal está totalmente desacoplado. Suele aparecer en arquitecturas como el origen para ser migrado a una arquitectura de microservicios.
Ali hablar de patrones de arquitectura, es muy conveniente mencionar el concepto de arquitectura limpia. La Clean Architecture (o arquitectura limpia) es un patrón de diseño de software que busca crear aplicaciones con un código limpio, bien estructurado y fácil de mantener. Fue propuesta por Robert C. Martin, también conocido como ‘Uncle Bob’. El principal objetivo de esta arquitectura es separar las diferentes capas de una aplicación, de modo que cada una tenga una responsabilidad claramente definida y esté desacoplada de las demás.
La Clean Architecture sigue el principio de la Independencia de UI (User Interface), lo que significa que las capas más internas no dependen de las capas externas. Esto permite que los cambios en la interfaz de usuario o en los detalles técnicos no afecten a la lógica de negocio central, lo que hace que la aplicación sea más flexible y fácil de adaptar.
Las capas principales de la Clean Architecture son:
Supongamos que estamos construyendo un sistema de e-commerce basado en microservicios. Cada microservicio representa una funcionalidad específica, como la gestión de productos, el procesamiento de pedidos y la autenticación de usuarios.
Vamos a aplicar la Clean Architecture a esta situación teniendo en cuenta que vamos a implementar el microservicio de gestión de productos:
public class Product {
private String name;
private double price;
private int stock;
// Getters and setters
}
public interface AddProductUseCase {
void addProduct(Product product);
}
public interface PurchaseUseCase {
void purchaseProduct(Product product, int quantity);
}
public interface ViewAllProductsUseCase {
List<Product> getAllProducts();
}
public class ProductController {
private AddProductUseCase addProductUseCase;
private PurchaseUseCase purchaseUseCase;
private ViewAllProductsUseCase viewAllProductsUseCase;
//Constructor e inyección de dependencias
@PostMapping("/products") public
ResponseEntity<String> addProduct(@RequestBody Product product) {
addProductUseCase.addProduct(product);
return ResponseEntity.ok("Product added successfully");
}
@PostMapping("/purchase")
public ResponseEntity<String> purchaseProduct(@RequestBody PurchaseRequest purchaseRequest) {
Product product = getProductById(purchaseRequest.getProductId());
purchaseUseCase.purchaseProduct(product, purchaseRequest.getQuantity());
return ResponseEntity.ok("Purchase successful");
}
@GetMapping("/products") public ResponseEntity<List<Product>> getAllProducts() {
List<Product> products = viewAllProductsUseCase.getAllProducts();
return ResponseEntity.ok(products);
}
}
@Repository
public class ProductRepositoryImpl implements ProductRepository {
private List<Product> productList = new ArrayList<>();
@Override
public void save(Product product) {
productList.add(product);
}
@Override
public List<Product> findAll() {
return productList;
}
}
Con la Clean Architecture logramos una organización clara de nuestra aplicación. Los casos de uso y entidades están aislados de los detalles técnicos y de la interfaz de usuario, lo que nos brinda la flexibilidad para realizar cambios y mejoras sin afectar otras partes de la aplicación.
Clean Architecture aporta varios beneficios significativos al diseño y desarrollo de microservicios en un sistema. Estos beneficios se derivan de su enfoque en la separación de responsabilidades y la creación de un código modular y mantenible. Aquí hay algunas formas en las que la Clean Architecture agrega valor a los microservicios:
Clean Architecture proporciona una base sólida para el diseño y desarrollo de microservicios al promover la modularidad, el desacoplamiento y la flexibilidad. Estos atributos son cruciales para crear microservicios que sean mantenibles, escalables y adaptables en un entorno en constante cambio.
El patrón Database per Microservice (base de datos por microservicio) es una estrategia arquitectónica que sugiere que cada microservicio tenga su propia base de datos independiente y dedicada. En lugar de compartir una única base de datos centralizada, cada microservicio tiene su propio esquema y base de datos, lo que permite que los microservicios sean más autónomos y evita el acoplamiento entre ellos en términos de almacenamiento de datos.
Este enfoque busca lograr una mayor independencia y escalabilidad entre los microservicios. Cada microservicio puede elegir la tecnología y el tipo de base de datos más adecuado para su propósito, sin afectar a los demás servicios. Además, la base de datos dedicada facilita el escalamiento individual de los microservicios según sus necesidades de carga y acceso a datos.
El patrón Database per Microservice tiene varias ventajas:
A pesar de las ventajas, el enfoque Database per Microservice también tiene desafíos y consideraciones:
Veamos un ejemplo:
Supongamos que tenemos varios microservicios en una aplicación de comercio electrónico. Seguimos con el ejemplo de un e-commerce.
En el ejemplo vamos a ver qué motivos nos llevarían a elegir una BBDD u otra, no siempre hay una única solución buena, por lo que todo es debatible y todo puede cambiar en función de las demandas del tipo de aplicación. Otro punto imprescindible a la hora de tomar decisiones es el coste, tener diferentes BBDD, licencias, clusters puede hacer inviable económicamente un proyecto, así que también se puede ir creciendo con la necesidad. No olvidemos que estamos poniendo un ejemplo orientado al patrón descrito.
Cada microservicio puede elegir la tecnología de base de datos más adecuada para sus necesidades. Esto permite que los equipos de desarrollo trabajen de manera independiente y evita que los cambios en un microservicio afecten a la base de datos de otro. Sin embargo, si se requiere información combinada de productos y pedidos, será necesario implementar una estrategia de integración de datos.
En resumen, el patrón Database per Microservice es una estrategia que brinda independencia y escalabilidad a los microservicios, pero también introduce desafíos de consistencia y administración de datos. La elección de este patrón debe hacerse considerando las necesidades y requisitos específicos de la aplicación.
En este post hemos hecho una primera aproximación a la arquitectura de microservicios. Hemos repasado qué es, qué ventajas tiene y qué nos puede aportar. Además, hemos hablado de algunos de los patrones de arquitectura de microservicios como patrón MVC, Clean Architecture o Database per Microservice.
Pero nos queda mucho más:
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.
Cuéntanos qué te parece.