Intercambio de mensajes en la nube en la plataforma Red Hat OpenShift utilizando Quarkus y AMQ Online

¡Hola a todos! Aquí está nuestro último post de la serie sobre Quarkus! (Por cierto, vean nuestro seminario web «Esto es Quarkus: un marco de trabajo Java nativo de Kubernetes». Mostraremos cómo comenzar «desde cero» o migrar soluciones existentes)

Intercambio de mensajes en la nube en la plataforma Red Hat OpenShift utilizando Quarkus y AMQ Online

En anterior en el que revisamos las herramientas adecuadas para evaluar cuantitativamente las mejoras obtenidas como resultado de la modernización de aplicaciones Java.

A partir de la versión 0.17.0, Quarkus se admite el uso de Advanced Message Queuing Protocol (AMQP), que es un estándar abierto para la transmisión de mensajes de negocio entre aplicaciones u organizaciones.

Red Hat AMQ Online es un servicio construido sobre el proyecto abierto EnMasse y implementa un mecanismo de intercambio de mensajes basado en la plataforma Red Hat OpenShift. Para más detalles sobre su funcionamiento, véalo aquí (EN). Hoy mostraremos cómo combinar AMQ Online y Quarkus para construir un sistema moderno de intercambio de mensajes en OpenShift utilizando dos nuevas tecnologías relacionadas con el procesamiento de mensajes.

Se supone que ya ha desplegado AMQ Online en la plataforma OpenShift (si no, vea la guía de instalación).

Para comenzar, crearemos una aplicación Quarkus que representará un simple sistema de procesamiento de pedidos utilizando intercambio de mensajes reactivo. Esta aplicación incluirá un generador de pedidos que enviará pedidos a la cola de mensajes a intervalos fijos, así como un procesador de pedidos que procesará los mensajes de la cola y generará confirmaciones disponibles para ver en el navegador.

Después de crear la aplicación, mostraremos cómo integrar la configuración del sistema de intercambio de mensajes y utilizaremos AMQ Online para inicializar los recursos necesarios en este sistema.

Aplicación Quarkus

Nuestra aplicación Quarkus se ejecuta en OpenShift y es una versión modificada del programa amqp-quickstart. Un ejemplo completo de la parte del cliente se puede encontrar aquí.

Generador de pedidos

El generador envía cada 5 segundos de manera monótona identificadores crecientes de pedidos a la dirección 'orders'.

@ApplicationScoped
public class OrderGenerator {
 
    private int orderId = 1;
 
    @Outgoing("orders")
    public Flowable generate() {
        return Flowable.interval(5, TimeUnit.SECONDS)
        .map(tick -> orderId++);
    }
}

Procesador de pedidos

El procesador de pedidos es aún más sencillo, simplemente devuelve el identificador de confirmación a la dirección 'confirmations'.

@ApplicationScoped
public class OrderProcessor {
    @Incoming("orders")
    @Outgoing("confirmations")
    public Integer process(Integer order) {
        // El identificador de la confirmación es igual al doble del identificador del pedido <img draggable="false" class="emoji" alt=":-)" src="https://s.w.org/images/core/emoji/11.2.0/svg/1f642.svg">
        return order * 2;
    }
}

Recursos de confirmación

El recurso de confirmación es un punto final HTTP para listar las confirmaciones generadas como resultado del funcionamiento de nuestra aplicación.

@Path("/confirmations")
public class ConfirmationResource {
 
    @Inject
    @Stream("confirmations") Publisher orders;
 
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hola";
    }
 
 
    @GET
    @Path("/stream")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public Publisher stream() {
        return orders;
    }
}

Configuración

Para conectarse a AMQ Online, nuestra aplicación necesitará algunos datos de configuración, específicamente: la configuración del conector Quarkus, la información del punto final AMQP y las credenciales del cliente. Es mejor, por supuesto, mantener todos los datos de configuración en un solo lugar, pero los separaremos aquí para mostrar posibles opciones de configuración de la aplicación Quarkus.

Conectores

La configuración del conector se puede proporcionar en tiempo de compilación mediante un archivo de propiedades de la aplicación:

mp.messaging.outgoing.orders.connector=smallrye-amqp
mp.messaging.incoming.orders.connector=smallrye-amqp

Para simplificar, utilizaremos una cola de mensajes solo para la dirección "orders". La dirección "confirmations" en nuestra aplicación usará una cola en memoria.

Punto final AMQP

En tiempo de compilación, el nombre del host y el número de puerto para el punto final AMQP no son conocidos, por lo que deben ser inyectados. El punto final se puede definir en el configmap que crea AMQ Online, por lo que los definiremos a través de variables de entorno en el manifiesto de la aplicación:

spec:
  template:
    spec:
      containers:
      - env:
        - name: AMQP_HOST
          valueFrom:
            configMapKeyRef:
              name: quarkus-config
              key: service.host
        - name: AMQP_PORT
          valueFrom:
            configMapKeyRef:
              name: quarkus-config
              key: service.port.amqp

Credenciales

El token de cuenta de servicio se puede usar para autenticar nuestra aplicación en OpenShift. Para ello, primero hay que crear un ConfigSource personalizado que lea el token de autenticación del sistema de archivos del pod:

public class MessagingCredentialsConfigSource implements ConfigSource {
    private static final Set propertyNames;
 
    static {
        propertyNames = new HashSet();
        propertyNames.add("amqp-username");
        propertyNames.add("amqp-password");
    }
 
    @Override
    public Set getPropertyNames() {
        return propertyNames;
    }
 
    @Override
    public Map getProperties() {
        try {
            Map properties = new HashMap();
            properties.put("amqp-username", "@@serviceaccount@@");
            properties.put("amqp-password", readTokenFromFile());
            return properties;
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
 
    @Override
    public String getValue(String key) {
        if ("amqp-username".equals(key)) {
            return "@@serviceaccount@@";
        }
        if ("amqp-password".equals(key)) {
            try {
                return readTokenFromFile();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }
        return null;
    }
 
    @Override
    public String getName() {
        return "messaging-credentials-config";
    }
 
    private static String readTokenFromFile() throws IOException {
        return new String(Files.readAllBytes(Paths.get("/var/run/secrets/kubernetes.io/serviceaccount/token")), StandardCharsets.UTF_8);
    }
}

Compilación y despliegue de la aplicación

Dado que la aplicación debe ser compilada en un archivo ejecutable, se necesitará una máquina virtual GraalVM. Para obtener más detalles sobre cómo configurar el entorno para esto, consulte las instrucciones correspondientes en Guía de Quarkus.

Luego, siguiendo las instrucciones allí dadas, se debe descargar el código fuente, realizar la compilación y desplegar nuestra aplicación:

git clone https://github.com/EnMasseProject/enmasse-example-clients
cd enmasse-example-clients/quarkus-example-client
oc new-project myapp
mvn -Pnative -Dfabric8.mode=openshift -Dfabric8.build.strategy=docker package fabric8:build fabric8:resource fabric8:apply

Después de estos comandos, la aplicación se desplegará, pero no se iniciará hasta que configuremos en AMQ Online los recursos necesarios para el intercambio de mensajes.

Configuración del sistema de intercambio de mensajes

Ahora solo queda definir en el sistema de intercambio de mensajes los recursos necesarios para nuestra aplicación. Para ello, es necesario crear: 1) un espacio de direcciones para inicializar el punto final del sistema de intercambio de mensajes; 2) una dirección para configurar las direcciones que utilizamos en la aplicación; 3) un usuario del sistema de intercambio de mensajes para establecer las credenciales del cliente.

Espacio de direcciones

El objeto AddressSpace en AMQ Online es un grupo de direcciones que comparten puntos finales de conexión, así como políticas de autenticación y autorización. Al crear un espacio de direcciones, se puede especificar cómo se proporcionarán los puntos finales del sistema de intercambio de mensajes:

apiVersion: enmasse.io/v1beta1
kind: AddressSpace
metadata:
  name: quarkus-example
spec:
  type: brokered
  plan: brokered-single-broker
  endpoints:
  - name: messaging
    service: messaging
    exports:
    - name: quarkus-config
      kind: configmap

Dirección

Las direcciones se utilizan para enviar y recibir mensajes. Cada dirección tiene un tipo que define su semántica, así como un plan que establece la cantidad de recursos reservados. Una dirección se puede definir, por ejemplo, de esta manera:

apiVersion: enmasse.io/v1beta1
kind: Address
metadata:
  name: quarkus-example.orders
spec:
  address: orders
  type: queue
  plan: brokered-queue

Usuario del sistema de mensajería

Para que solo las aplicaciones de confianza puedan enviar y recibir mensajes en sus direcciones, es necesario crear un usuario en el sistema de mensajería. Para las aplicaciones que se ejecutan en el clúster, los clientes se pueden autenticar usando la cuenta de servicio de OpenShift. Un usuario 'serviceaccount' se puede definir, por ejemplo, de esta manera:

apiVersion: user.enmasse.io/v1beta1
kind: MessagingUser
metadata:
  name: quarkus-example.app
spec:
  username: system:serviceaccount:myapp:default
  authentication:
    type: serviceaccount
  authorization:
  - operations: ["send", "recv"]
    addresses: ["orders"]

Permisos para configurar la aplicación

Para que AMQ Online pueda crear el configmap que utilizamos para insertar información sobre el punto final AMQP, es necesario definir un rol y un enlace de rol (Role y RoleBinding):

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: quarkus-config
spec:
  rules:
  - apiGroups: [ "" ]
    resources: [ "configmaps" ]
    verbs: [ "create" ]
  - apiGroups: [ "" ]
    resources: [ "configmaps" ]
    resourceNames: [ "quarkus-config" ]
    verbs: [ "get", "update", "patch" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: quarkus-config
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: quarkus-config
subjects:
- kind: ServiceAccount
  name: address-space-controller
  namespace: amq-online-infra

Cómo aplicar configuraciones

La configuración del sistema de mensajería se puede aplicar de la siguiente manera:

cd enmasse-example-clients/quarkus-example-client
oc project myapp
oc apply -f src/main/resources/k8s/addressspace
oc apply -f src/main/resources/k8s/address

Verificación de la aplicación

Para asegurarnos de que la aplicación se ha iniciado correctamente, primero verificaremos si las direcciones correspondientes han sido creadas y están activas:

until [[ `oc get address quarkus-example.prices -o jsonpath='{.status.phase}'` == "Active" ]]; do echo "No está listo todavía"; sleep 5; done

Luego verificaremos la URL de la ruta de la aplicación (simplemente abriremos esta dirección en el navegador):

echo "http://$(oc get route quarkus-example-client -o jsonpath='{.spec.host}')/prices.html"

En el navegador debería verse que los tickets se actualizan periódicamente a medida que los mensajes son enviados y recibidos por AMQ Online.

Resumen

Así que hemos escrito una aplicación Quarkus que utiliza AMQP para la mensajería, configuramos esta aplicación para funcionar en la plataforma Red Hat OpenShift, y también implementamos su configuración basada en la configuración de AMQ Online. Luego creamos los manifiestos necesarios para inicializar el sistema de mensajería para nuestra aplicación.

Con esto concluimos nuestra serie sobre Quarkus, pero se viene mucho más interesante, ¡quédense con nosotros!

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster