diff --git a/localization/es/ambassador/README.md b/localization/es/ambassador/README.md new file mode 100644 index 000000000..fcc63208e --- /dev/null +++ b/localization/es/ambassador/README.md @@ -0,0 +1,208 @@ +--- +title: Ambassador +category: Structural +language: es +tag: + - Decoupling + - Cloud distributed +--- + +## Motivo + +Proporcionar una instancia de servicio auxiliar a un cliente y delegar en ella las funcionalidades comunes de un recurso compartido. + +## Explicación + +Ejemplo real + +> Un servicio remoto tiene muchos clientes accediendo a una función que este servicio proporciona. El servicio es una aplicación heredada y +> es imposible actualizarla. Un gran número de solicitudes por parte de los usuarios están causando problemas de conectividad. Nuevas reglas +> respecto a la frecuencia de solicitudes deberían implementarse junto con comprobaciones de latencia y registros del lado del cliente. + +En otras palabras + +> Con el patrón Ambassador, podemos implementar una menor frecuencia en solicitudes de clientes junto con comprobaciones de latencia y +> registros. + +Según la Documentación de Microsoft + +> Un servicio de Ambassador puede considerarse como un proxy fuera de proceso que coexiste con el cliente. +> +> Este patrón puede ser útil para la descarga de tareas comunes de conectividad de cliente, como la supervisión, el registro, el enrutamiento, +> la seguridad (por ejemplo, TLS) y los patrones de resistencia(*) de una manera independiente del lenguaje. A menudo se utiliza con aplicaciones heredadas, +> u otras aplicaciones que son difíciles de modificar, con el fin de ampliar sus capacidades de red. También puede +> habilitar un equipo especializado para implementar esas características. + +**Código de ejemplo** + +Con la introducción anterior en mente vamos a imitar su funcionalidad en el siguiente ejemplo. Tenemos una interface implementada +por el servicio remoto así como el servicio ambassador: + +```java +interface RemoteServiceInterface { + long doRemoteFunction(int value) throws Exception; +} +``` + +Un servicio remoto representado como un singleton (Instancia única). + +```java +@Slf4j +public class RemoteService implements RemoteServiceInterface { + private static RemoteService service = null; + + static synchronized RemoteService getRemoteService() { + if (service == null) { + service = new RemoteService(); + } + return service; + } + + private RemoteService() {} + + @Override + public long doRemoteFunction(int value) { + long waitTime = (long) Math.floor(Math.random() * 1000); + + try { + sleep(waitTime); + } catch (InterruptedException e) { + LOGGER.error("Thread sleep interrupted", e); + } + + return waitTime >= 200 ? value * 10 : -1; + } +} +``` + +Un servicio ambassador añadiendo funcionalidades adicionales como registros, comprobación de latencia + +```java +@Slf4j +public class ServiceAmbassador implements RemoteServiceInterface { + private static final int RETRIES = 3; + private static final int DELAY_MS = 3000; + + ServiceAmbassador() { + } + + @Override + public long doRemoteFunction(int value) { + return safeCall(value); + } + + private long checkLatency(int value) { + var startTime = System.currentTimeMillis(); + var result = RemoteService.getRemoteService().doRemoteFunction(value); + var timeTaken = System.currentTimeMillis() - startTime; + + LOGGER.info("Time taken (ms): " + timeTaken); + return result; + } + + private long safeCall(int value) { + var retries = 0; + var result = (long) FAILURE; + + for (int i = 0; i < RETRIES; i++) { + if (retries >= RETRIES) { + return FAILURE; + } + + if ((result = checkLatency(value)) == FAILURE) { + LOGGER.info("Failed to reach remote: (" + (i + 1) + ")"); + retries++; + try { + sleep(DELAY_MS); + } catch (InterruptedException e) { + LOGGER.error("Thread sleep state interrupted", e); + } + } else { + break; + } + } + return result; + } +} +``` + +Un cliente tiene un servicio ambassador local usado para interactuar con el servicio remoto: + +```java +@Slf4j +public class Client { + private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador(); + + long useService(int value) { + var result = serviceAmbassador.doRemoteFunction(value); + LOGGER.info("Service result: " + result); + return result; + } +} +``` + +A continuación dos clientes usando el servicio. + +```java +public class App { + public static void main(String[] args) { + var host1 = new Client(); + var host2 = new Client(); + host1.useService(12); + host2.useService(73); + } +} +``` + +Esta es la salida que obtendremos tras ejecutar el ejemplo: + +```java +Time taken (ms): 111 +Service result: 120 +Time taken (ms): 931 +Failed to reach remote: (1) +Time taken (ms): 665 +Failed to reach remote: (2) +Time taken (ms): 538 +Failed to reach remote: (3) +Service result: -1 +``` + +## Diagrama de clase + +![alt text](/ambassador/etc/ambassador.urm.png "Ambassador class diagram") + +## Aplicaciones + +Ambassador es aplicable cuando trabajamos con un servicio remoto heredado que no puede ser modificado o que sería extremamente +difícil de modificar. Las características de conectividad pueden implementarse en el cliente sin necesidad de realizar cambios en el servicio +remoto. + +* Ambassador proporciona una interface local para un servicio remoto. +* Ambassador proporciona registros, interrupción de circuitos, reintentos y seguridad en el cliente. + +## Casos de uso típicos + +* Control de acceso a otro objeto +* Implementación de registros o logs +* Implementación de interrupciones de circuito +* Delegar tareas de servicios remotos +* Facilitar la conexión a la red + +## Usos conocidos + +* [Pasarela API Kubernetes-native para microservicios](https://github.com/datawire/ambassador) + +## Patrones relacionados + +* [Proxy](https://java-design-patterns.com/patterns/proxy/) + +## Créditos + +* [Ambassador Pattern (Documentación de Microsoft en inglés)](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador) +* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://www.amazon.com/s?k=designing+distributed+systems&sprefix=designing+distri%2Caps%2C156&linkCode=ll2&tag=javadesignpat-20&linkId=a12581e625462f9038557b01794e5341&language=en_US&ref_=as_li_ss_tl) + +## Notas del traductor +(*) La versión original en inglés de la documentación de Microsoft hace referencia al término resiliencia y +en su traducción al español lo traduce como resistencia, aunque enlaza al apartado patrones de confiabilidad. Véase: +* [Versión de la Documentación para el Patrón Ambassador de Microsoft en español.](https://learn.microsoft.com/es-es/azure/architecture/patterns/ambassador)