"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¿Por qué descartamos la arquitectura de sistemas reactivos de nuestro código?

¿Por qué descartamos la arquitectura de sistemas reactivos de nuestro código?

Publicado el 2024-09-02
Navegar:715

Este artículo explora nuestra decisión de alejarnos de la arquitectura reactiva en nuestro proyecto de software. Profundizaremos en los principios básicos de los sistemas reactivos, los beneficios de las E/S sin bloqueo y los desafíos que enfrentamos con un enfoque reactivo.

Comprender el estilo de arquitectura reactiva

Reactivo abarca un conjunto de principios y directrices destinados a construir sistemas y aplicaciones distribuidos responsivos, caracterizados por:

  1. Capacidad de respuesta: Capaz de manejar solicitudes rápidamente, incluso bajo cargas pesadas.
  2. Resiliencia: Capaz de recuperarse de fallas con un tiempo de inactividad mínimo.
  3. Elasticidad: Puede adaptarse a cargas de trabajo cambiantes escalando los recursos en consecuencia.
  4. Basado en mensajes: Utiliza mensajería asincrónica para mejorar la tolerancia a fallas y desacoplar componentes.

Un beneficio clave de los sistemas reactivos es el uso de E/S sin bloqueo. Este enfoque evita el bloqueo de subprocesos durante las operaciones de E/S, lo que permite que un solo subproceso maneje múltiples solicitudes al mismo tiempo. Esto puede mejorar significativamente la eficiencia del sistema en comparación con el bloqueo de E/S tradicional.
En el multiproceso tradicional, las operaciones de bloqueo plantean desafíos importantes a la hora de optimizar los sistemas (Figura 1). Las aplicaciones codiciosas que consumen demasiada memoria son ineficientes y penalizan a otras aplicaciones, y a menudo requieren solicitudes de recursos adicionales como memoria, CPU o máquinas virtuales más grandes.

Why we discarded Reactive systems architecture from our code?

Figura 1: subprocesos múltiples tradicionales


Las operaciones de E/S son parte integral de los sistemas modernos, y administrarlas de manera eficiente es fundamental para evitar comportamientos codiciosos. Los sistemas reactivos emplean E/S sin bloqueo, lo que permite que una pequeña cantidad de subprocesos del sistema operativo manejen numerosas operaciones de E/S simultáneas.

Modelo de ejecución reactiva

Aunque la E/S sin bloqueo ofrece beneficios sustanciales, introduce un modelo de ejecución novedoso distinto de los marcos tradicionales. La programación reactiva surgió para abordar este problema, ya que mitiga la ineficiencia de los subprocesos de la plataforma inactivos durante las operaciones de bloqueo (Figura 2).

Why we discarded Reactive systems architecture from our code?

Figura 2: bucle de evento reactivo


Quarkus y reactivo

Quarkus aprovecha un motor reactivo impulsado por Eclipse Vert.x y Netty, lo que facilita interacciones de E/S sin bloqueo. Mutiny, el enfoque preferido para escribir código reactivo con Quarkus, adopta un paradigma basado en eventos, en el que las reacciones se desencadenan mediante eventos recibidos.

Mutiny ofrece dos tipos basados ​​en eventos y diferidos:

  1. Uni: Emite un único evento (un elemento o una falla), adecuado para representar acciones asincrónicas con cero o un resultado.
  2. Multi: Emite múltiples eventos (n elementos, un error o una finalización), que representan flujos de elementos, potencialmente ilimitados.

Desafíos con reactivo

Si bien los sistemas reactivos ofrecen beneficios, encontramos varios desafíos durante el desarrollo:

  • Cambio de paradigma: La programación reactiva requiere un cambio fundamental en la mentalidad de los desarrolladores, lo que puede ser un desafío, especialmente para los desarrolladores acostumbrados a la programación imperativa. A diferencia de las herramientas auxiliares como Streams API, el enfoque reactivo exige una revisión completa de la mentalidad.
  • Legibilidad y comprensión del código: El código reactivo plantea dificultades para que los nuevos desarrolladores lo comprendan, lo que lleva a un mayor tiempo dedicado a descifrarlo y comprenderlo. La complejidad introducida por los paradigmas reactivos agrava este problema.

"De hecho, la proporción de tiempo dedicado a leer versus escribir es muy superior a 10 a 1. Leemos constantemente código antiguo como parte del esfuerzo por escribir código nuevo. ...[Por lo tanto,] facilitar la lectura facilita es más fácil escribir."
Robert C. Martin, Código limpio: un manual de artesanía de software ágil

  • Desafíos de depuración: La depuración de código reactivo resulta casi imposible con los depuradores IDE estándar debido a que las lambdas encapsulan la mayor parte del código. Además, la pérdida de seguimientos de pila significativos durante las excepciones dificulta aún más los esfuerzos de depuración. Mayores esfuerzos de desarrollo y pruebas: La complejidad inherente del código reactivo puede llevar a ciclos de desarrollo más largos debido al tiempo requerido para escribir, modificar y probar.

Aquí hay un ejemplo de código reactivo que usa Mutiny para ilustrar la complejidad:

Multi.createFrom().ticks().every(Duration.ofSeconds(15))
    .onItem().invoke(() - > Multi.createFrom().iterable(configs())
    .onItem().transform(configuration - > {
  try {
    return Tuple2.of(openAPIConfiguration,
        RestClientBuilder.newBuilder()
            .baseUrl(new URL(configuration.url()))
            .build(MyReactiveRestClient.class)
            .getAPIResponse());

  } catch (MalformedURLException e) {
    log.error("Unable to create url");

  }
  return null;
}).collect().asList().toMulti().onItem().transformToMultiAndConcatenate(tuples - > {

  AtomicInteger callbackCount = new AtomicInteger();
  return Multi.createFrom().emitter(emitter - > Multi.createFrom().iterable(tuples)
      .subscribe().with(tuple - >
          tuple.getItem2().subscribe().with(response - > {
              emitter.emit(callbackCount.incrementAndGet());

  if (callbackCount.get() == tuples.size()) {
    emitter.complete();
  }
                    })
                ));

}).subscribe().with(s - > {},
Throwable::printStackTrace, () - > doSomethingUponComplete()))
    .subscribe().with(aLong - > log.info("Tic Tac with iteration: "   aLong));

Perspectivas futuras: proyecto en telar y más allá

Project Loom, un desarrollo reciente en el ecosistema Java, promete mitigar los problemas asociados con las operaciones de bloqueo. Al permitir la creación de miles de subprocesos virtuales sin cambios de hardware, Project Loom podría eliminar potencialmente la necesidad de un enfoque reactivo en muchos casos.

"Project Loom va a acabar con la programación reactiva"
Brian Goetz

Conclusión

En conclusión, nuestra decisión de alejarnos del estilo de arquitectura reactiva y adoptar un enfoque pragmático para la mantenibilidad a largo plazo de nuestro proyecto. Si bien los sistemas reactivos ofrecen beneficios potenciales, los desafíos que presentaron para nuestro equipo superaron esas ventajas en nuestro contexto específico.

Es importante destacar que este cambio no comprometió el rendimiento. Este es un resultado positivo, ya que demuestra que una arquitectura no reactiva (imperativa) bien diseñada puede ofrecer el rendimiento necesario sin la complejidad asociada con la arquitectura reactiva en nuestro caso.

Mientras miramos hacia el futuro, el enfoque sigue siendo construir una base de código que no solo sea funcional sino también fácil de entender y mantener para desarrolladores de todos los niveles de experiencia. Esto no solo reduce el tiempo de desarrollo sino que también fomenta una mejor colaboración y el intercambio de conocimientos dentro del equipo.

En el siguiente gráfico, el eje X representa la creciente complejidad de nuestra base de código a medida que evoluciona, mientras que el eje Y representa el tiempo necesario para estos cambios de desarrollo.

Why we discarded Reactive systems architecture from our code?

Declaración de liberación Este artículo se reproduce en: https://dev.to/yanev/why-we-discarded-reactive-systems-architecture-from-our-code-19ni?1 Si hay alguna infracción, comuníquese con [email protected] para borrarlo
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3