Messagerie cloud Red Hat OpenShift utilisant Quarkus et AMQ Online

Bonjour à tous! Le voici - notre dernier article de la série Quarkus! (Soit dit en passant, consultez notre webinaire «C'est le framework Java natif de Quarkus - Kubernetes» . Nous montrerons comment recommencer à zéro ou transférer des solutions prêtes à l'emploi)



Dans un article précédent, nous avons examiné les outils appropriés avec lesquels vous pouvez quantifier les améliorations apportées à la suite de la modernisation de Java. applications.

À partir de la version 0.17.0, Quarkus prend en charge l'utilisation du protocole Advanced Message Queuing Protocol ( AMQP ), qui est une norme ouverte pour le transfert de messages d'entreprise entre des applications ou des organisations.

Red Hat AMQ Online est un service construit sur la base du projet open EnMasse et implémente un mécanisme de messagerie basé sur la plate-forme Red Hat OpenShift . Pour en savoir plus sur son fonctionnement, voir ici (vers EN) . Aujourd'hui, nous montrons comment combiner AMQ Online et Quarkus pour créer un système de messagerie moderne basé sur OpenShift en utilisant deux nouvelles technologies liées au traitement des messages.

Il est supposé que vous avez déjà déployé AMQ Online sur la plate-forme OpenShift (sinon, consultez le guide d'installation ).

Pour commencer, nous allons créer l'application Quarkus, qui sera un simple système de traitement des commandes utilisant la messagerie réactive. Cette application comprendra un générateur de commandes qui envoie des commandes à la file d'attente de messages avec un intervalle fixe, ainsi qu'un processeur de commandes qui traitera les messages de la file d'attente et générera des confirmations disponibles pour visualisation dans le navigateur.

Après avoir créé l'application, nous montrerons comment implémenter la configuration du système de messagerie et utiliser AMQ Online pour initialiser les ressources dont nous avons besoin sur ce système.

Application Quarkus


Notre application Quarkus fonctionne sur OpenShift et est une version modifiée de amqp-quickstart . Un exemple complet du côté client peut être trouvé ici .

Générateur de commandes


Le générateur toutes les 5 secondes envoie simplement de manière monotone des identifiants de commande croissants à l'adresse «commandes».

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

Gestionnaire de commandes


Le processeur de commande est encore plus simple, il renvoie simplement l'identifiant de confirmation à l'adresse «confirmations».

@ApplicationScoped
public class OrderProcessor {
    @Incoming("orders")
    @Outgoing("confirmations")
    public Integer process(Integer order) {
        //       <img draggable="false" class="emoji" alt=":-)" src="https://s.w.org/images/core/emoji/11.2.0/svg/1f642.svg">
        return order * 2;
    }
}

Ressources de confirmation


Une ressource de confirmation est un point de terminaison HTTP pour répertorier les confirmations générées par notre application.

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

Personnalisation


Pour se connecter à AMQ Online, notre application aura besoin de certaines données de configuration, à savoir: la configuration du connecteur Quarkus, les informations de point de terminaison AMQP et les informations d'identification du client. Il est bien sûr préférable de conserver toutes les données de configuration en un seul endroit, mais nous les séparerons spécialement pour afficher les options possibles pour la configuration de l'application Quarkus.

Connecteurs


La configuration du connecteur peut être fournie au stade de la compilation à l'aide du fichier de propriétés d'application:

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

Afin de ne pas compliquer cela, nous n'utiliserons la file d'attente de messages que pour l'adresse «commandes». Et l'adresse «confirmations» dans notre application utilisera la file d'attente en mémoire.

Endpoint AMQP


Au stade de la compilation, le nom d'hôte et le numéro de port du point de terminaison AMQP sont inconnus, ils doivent donc être implémentés. Le point de terminaison peut être défini dans la configmap, qui est créée par AMQ Online, nous allons donc les définir via les variables d'environnement dans le manifeste de l'application:

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

Identifiants


Le jeton de compte de service peut être utilisé pour authentifier notre application dans OpenShift. Pour ce faire, vous devez d'abord créer un ConfigSource personnalisé qui lira le jeton d'authentification à partir du système de fichiers pod:

public class MessagingCredentialsConfigSource implements ConfigSource {
    private static final Set<String> propertyNames;
 
    static {
        propertyNames = new HashSet<>();
        propertyNames.add("amqp-username");
        propertyNames.add("amqp-password");
    }
 
    @Override
    public Set<String> getPropertyNames() {
        return propertyNames;
    }
 
    @Override
    public Map<String, String> getProperties() {
        try {
            Map<String, String> 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);
    }
}

Assemblage et déploiement de l'application


Étant donné que l'application doit être compilée dans un fichier exécutable, une machine virtuelle GraalVM est requise. Pour plus d'informations sur la configuration d'un environnement à cet effet, consultez les instructions associées dans le Guide Quarkus .

Ensuite, en suivant les instructions, vous devez télécharger la source, créer et déployer notre application:

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

Après ces commandes, l'application sera déployée, mais ne démarrera pas tant que nous n'aurons pas configuré les ressources de messagerie nécessaires dans AMQ Online.

Configuration de la messagerie


Reste maintenant à définir les ressources dont notre application a besoin dans le système de messagerie. Pour ce faire, créez: 1) l'espace d'adressage pour initialiser le noeud final du système de messagerie; 2) l'adresse pour configurer les adresses que nous utilisons dans l'application; 3) l'utilisateur du système de messagerie pour définir les informations d'identification du client.

Espace d'adressage


L'objet AddressSpace dans AMQ Online est un groupe d'adresses qui partagent des points de terminaison de connexion, ainsi que des stratégies d'authentification et d'autorisation. Lors de la création d'un espace d'adressage, vous pouvez spécifier comment les noeuds finaux du système de messagerie seront fournis:

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

Adresses


Les adresses sont utilisées pour envoyer et recevoir des messages. Chaque adresse a un type qui définit sa sémantique, ainsi qu'un plan qui définit le nombre de ressources réservées. L'adresse peut être déterminée, par exemple, comme ceci:

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

Utilisateur de messagerie


Pour envoyer et recevoir des messages à vos adresses, seules les applications de confiance peuvent le faire, vous devez créer un utilisateur dans le système de messagerie. Pour les applications s'exécutant sur un cluster, les clients peuvent être authentifiés à l'aide d'un compte de service OpenShift. L'utilisateur "serviceaccount" peut être défini, par exemple, comme suit:

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"]

Autorisations pour personnaliser l'application


Pour qu'AMQ Online crée la carte de configuration que nous avons utilisée pour implémenter les informations de point de terminaison AMQP, vous devez spécifier le rôle et la liaison de rôle (Role et 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

Comment appliquer des configurations


Vous pouvez appliquer la configuration de messagerie comme ceci:

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

Vérification d'application


Pour nous assurer que l'application a démarré, nous allons tout d'abord vérifier si les adresses correspondantes sont créées et actives:

until [[ `oc get address quarkus-example.prices -o jsonpath='{.status.phase}'` == "Active" ]]; do echo "Not yet ready"; sleep 5; done

Vérifiez ensuite l'URL de l'itinéraire de l'application (ouvrez simplement cette adresse dans le navigateur):

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

Il doit être visible dans le navigateur que les tickets sont périodiquement mis à jour à mesure que les messages sont envoyés et reçus par AMQ Online.

Résumer


Nous avons donc écrit une application Quarkus qui utilise AMQP pour la messagerie, avons configuré cette application pour qu'elle fonctionne sur la plate-forme Red Hat OpenShift, et avons également implémenté sa configuration basée sur la configuration AMQ Online. Nous avons ensuite créé les manifestes nécessaires pour initialiser le système de messagerie de notre application.

Ceci conclut la série Quarkus, mais il y a beaucoup de choses nouvelles et intéressantes à venir, restez avec nous!

All Articles