Cloud-natives Messaging auf der Red Hat OpenShift-Plattform mit Quarkus und AMQ Online

Hallo zusammen! Hier ist er – unser letzter Beitrag in der Quarkus-Reihe! (Sehen Sie sich übrigens unser Webinar an „Das ist Quarkus – Kubernetes natives Java-Framework“. Wir zeigen Ihnen, wie Sie bei Null anfangen oder fertige Lösungen übertragen können)

Cloud-natives Messaging auf der Red Hat OpenShift-Plattform mit Quarkus und AMQ Online

В Bisherige In diesem Beitrag haben wir uns die relevanten Tools angesehen, mit denen sich die durch die Modernisierung von Java-Anwendungen erzielten Verbesserungen quantifizieren lassen.

Seit Version 0.17.0, Quark unterstützt die Verwendung des Advanced Message Queuing Protocol (AMQP), einem offenen Standard für die Übertragung von Geschäftsnachrichten zwischen Anwendungen oder Organisationen.

Red Hat AMQ Online ist ein Dienst, der auf der Grundlage eines Open-Source-Projekts erstellt wurde EnMasse und Implementierung eines plattformbasierten Nachrichtenmechanismus Red Hat OpenShift. Weitere Einzelheiten zur Funktionsweise finden Sie unter hier (EN). Heute zeigen wir Ihnen, wie Sie AMQ Online und Quarkus kombinieren, um ein modernes OpenShift-basiertes Messaging-System mit zwei neuen Messaging-Technologien aufzubauen.

Es wird davon ausgegangen, dass Sie AMQ Online bereits auf der OpenShift-Plattform bereitgestellt haben (falls nicht, dann siehe Installationsanleitung).

Zunächst erstellen wir eine Quarkus-Anwendung, die ein einfaches Auftragsverarbeitungssystem mit reaktivem Messaging darstellt. Diese Anwendung umfasst einen Bestellgenerator, der in einem festen Intervall Bestellungen an eine Nachrichtenwarteschlange sendet, sowie einen Bestellprozessor, der Nachrichten aus der Warteschlange verarbeitet und im Browser sichtbare Bestätigungen generiert.

Sobald wir die Anwendung erstellt haben, zeigen wir Ihnen, wie Sie die Messaging-Systemkonfiguration in die Anwendung einbetten und AMQ Online verwenden, um die benötigten Ressourcen auf dem System bereitzustellen.

Quarkus-App

Unsere Quarkus-Anwendung läuft auf OpenShift und ist eine modifizierte Version des Programms amqp-Schnellstart. Ein vollständiges Beispiel der Clientseite finden Sie hier hier.

Bestellgenerator

Der Generator sendet einfach monoton alle 5 Sekunden wachsende Bestell-IDs an die „Bestellungen“-Adresse.

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

Auftragsverarbeiter

Der Auftragsabwickler ist sogar noch einfacher, er sendet lediglich eine Bestätigungs-ID an die „Bestätigungs“-Adresse zurück.

@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;
    }
}

Ressourcen zur Konfirmation

Die Bestätigungsressource ist ein HTTP-Endpunkt zum Auflisten der von unserer Anwendung generierten Bestätigungen.

@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;
    }
}

Einstellung

Um eine Verbindung zu AMQ Online herzustellen, benötigt unsere Anwendung einige Konfigurationsdaten, nämlich: Quarkus-Connector-Konfiguration, AMQP-Endpunktinformationen und Client-Anmeldeinformationen. Natürlich ist es besser, alle Konfigurationsdaten an einem Ort aufzubewahren, wir werden sie jedoch bewusst trennen, um die möglichen Optionen zur Konfiguration der Quarkus-Anwendung aufzuzeigen.

Anschlüsse

Die Connector-Konfiguration kann zur Kompilierungszeit mithilfe einer Anwendungseigenschaftendatei bereitgestellt werden:

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

Der Einfachheit halber verwenden wir nur eine Nachrichtenwarteschlange für die Adresse „Bestellungen“. Und die „Bestätigungs“-Adresse in unserer Anwendung verwendet eine Warteschlange im Speicher.

AMQP-Endpunkt

Zur Kompilierungszeit sind der Hostname und die Portnummer für den AMQP-Endpunkt unbekannt und müssen daher eingefügt werden. Der Endpunkt kann in der von AMQ Online erstellten Konfigurationszuordnung festgelegt werden, daher definieren wir ihn über Umgebungsvariablen im Anwendungsmanifest:

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

Referenzen

Das Dienstkonto-Token kann zur Authentifizierung unserer Anwendung bei OpenShift verwendet werden. Dazu müssen Sie zunächst eine benutzerdefinierte ConfigSource erstellen, die das Authentifizierungstoken aus dem Dateisystem des Pods liest:

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);
    }
}

Erstellen Sie die Anwendung und stellen Sie sie bereit

Da die Anwendung in eine ausführbare Datei kompiliert werden muss, ist eine virtuelle GraalVM-Maschine erforderlich. Einzelheiten zum Einrichten einer Umgebung hierfür finden Sie in den entsprechenden Anweisungen in Quarkus-Führer.

Anschließend müssen Sie den dort gegebenen Anweisungen folgen und die Quelle herunterladen sowie unsere Anwendung erstellen und bereitstellen:

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

Nach diesen Befehlen wird die Anwendung bereitgestellt, aber erst gestartet, wenn wir die benötigten Messaging-Ressourcen in AMQ Online konfiguriert haben.

Einrichten des Nachrichtensystems

Jetzt müssen wir nur noch die Ressourcen festlegen, die unsere Anwendung im Nachrichtensystem benötigt. Dazu müssen Sie Folgendes erstellen: 1) einen Adressraum zum Initialisieren des Messaging-System-Endpunkts; 2) Adresse zum Konfigurieren der Adressen, die wir in der Anwendung verwenden; 3) Senden Sie dem Benutzer eine Nachricht, um die Anmeldeinformationen des Clients festzulegen.

Adressraum

Ein AddressSpace-Objekt in AMQ Online ist eine Gruppe von Adressen, die Verbindungsendpunkte sowie Authentifizierungs- und Autorisierungsrichtlinien gemeinsam nutzen. Wenn Sie einen Adressraum erstellen, können Sie angeben, wie Messaging-Endpunkte verfügbar gemacht werden:

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

Адреса

Adressen werden zum Senden und Empfangen von Nachrichten verwendet. Jede Adresse hat einen Typ, der ihre Semantik bestimmt, sowie einen Plan, der die Anzahl der zu reservierenden Ressourcen angibt. Die Adresse kann beispielsweise so ermittelt werden:

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

Nachrichtenbenutzer

Um sicherzustellen, dass nur vertrauenswürdige Anwendungen Nachrichten an Ihre Adressen senden und empfangen können, müssen Sie im Nachrichtensystem einen Benutzer erstellen. Für Anwendungen, die in einem Cluster ausgeführt werden, können Clients mithilfe eines OpenShift-Dienstkontos authentifiziert werden. Der Benutzer „serviceaccount“ kann beispielsweise so definiert werden:

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

Berechtigungen zum Konfigurieren der Anwendung

Damit AMQ Online die Konfigurationszuordnung erstellen kann, die wir zum Einbetten der AMQP-Endpunktinformationen verwendet haben, müssen Role und RoleBinding festgelegt werden:

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

So wenden Sie Konfigurationen an

Sie können die Konfiguration des Nachrichtensystems wie folgt anwenden:

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

Anwendungsüberprüfung

Um sicherzustellen, dass die Anwendung gestartet ist, prüfen wir zunächst, ob die entsprechenden Adressen erstellt wurden und aktiv sind:

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

Dann überprüfen wir die URL der Anwendungsroute (öffnen Sie einfach diese Adresse im Browser):

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

Der Browser sollte anzeigen, dass Tickets regelmäßig aktualisiert werden, wenn Nachrichten von AMQ Online gesendet und empfangen werden.

Zusammenfassend

Deshalb haben wir eine Quarkus-Anwendung geschrieben, die AMQP für die Nachrichtenübermittlung verwendet, die Anwendung für die Ausführung auf der Red Hat OpenShift-Plattform konfiguriert und ihre Konfiguration basierend auf der AMQ Online-Konfiguration implementiert. Anschließend haben wir die Manifeste erstellt, die zum Initialisieren des Nachrichtensystems für unsere Anwendung erforderlich sind.

Damit ist die Serie über Quarkus abgeschlossen, aber es liegen noch viele neue und interessante Dinge vor uns, bleiben Sie dran!

Source: habr.com

Kommentar hinzufügen