Chmurowo zorientowana wymiana wiadomości na platformie Red Hat OpenShift z użyciem Quarkus i AMQ Online

Cześć wszystkim! Oto on – nasz ostatni post z serii o Quarkus! (A propos, zobaczcie nasz webinar „To Quarkus – natywny dla Kubernetes framework Java”. Pokażemy, jak zacząć „od zera” lub przenieść gotowe rozwiązania)

Chmurowo zorientowana wymiana wiadomości na platformie Red Hat OpenShift z użyciem Quarkus i AMQ Online

W poprzednim w poście omówiliśmy odpowiednie narzędzia, za pomocą których można ilościowo ocenić udoskonalenia wynikające z modernizacji aplikacji Java.

Od wersji 0.17.0, Quarkus obsługuje użycie Advanced Message Queuing Protocol (AMQP), który jest otwartym standardem wymiany wiadomości biznesowych między aplikacjami lub organizacjami.

Red Hat AMQ Online – to usługa zbudowana na podstawie otwartego projektu EnMasse i implementująca mechanizm wymiany wiadomości oparty na platformie Red Hat OpenShift. Dowiedz się więcej o tym, jak to działa, przeczytaj tutaj (EN). Dziś pokażemy, jak połączyć AMQ Online z Quarkus, aby zbudować nowoczesny system wymiany wiadomości na OpenShift, wykorzystując dwie nowe technologie związane z przetwarzaniem wiadomości.

Zakłada się, że już wdrożyłeś AMQ Online na platformie OpenShift (jeśli nie, zobacz przewodnik instalacyjny).

Na początek stworzymy aplikację Quarkus, która będzie przedstawiać prosty system przetwarzania zamówień z użyciem reaktywnej wymiany wiadomości. Ta aplikacja będzie zawierać generator zamówień, który wysyła zamówienia do kolejki wiadomości z ustalonym interwałem, oraz przetwornik zamówień, który będzie obsługiwał wiadomości z kolejki i tworzył potwierdzenia dostępne do przeglądania w przeglądarce.

Po utworzeniu aplikacji pokażemy, jak wprowadzić w nią konfigurację systemu wymiany wiadomości i wykorzystamy AMQ Online, aby zainicjować potrzebne nam zasoby na tym systemie.

Aplikacja Quarkus

Nasza aplikacja Quarkus działa na OpenShift i jest zmodyfikowaną wersją programu amqp-quickstart. Pełny przykład części klienckiej można znaleźć tutaj.

Generator zamówień

Generator co 5 sekund monotonnie przesyła rosnące identyfikatory zamówień na adres „orders”.

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

Przetwornik zamówień

Przetwornik zamówień jest jeszcze prostszy, po prostu zwraca identyfikator potwierdzenia na adres „confirmations”.

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

Zasoby potwierdzeń

Zasób potwierdzenia to punkt końcowy HTTP do listowania potwierdzeń utworzonych przez nasze aplikacje.

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

Konfiguracja

Aby połączyć się z AMQ Online, nasza aplikacja potrzebuje pewnych danych konfiguracyjnych, a mianowicie: konfiguracji konektora Quarkus, informacji o punkcie końcowym AMQP oraz danych uwierzytelniających klienta. Oczywiście, najlepiej trzymać wszystkie dane konfiguracyjne w jednym miejscu, jednak specjalnie je rozdzielimy, aby pokazać możliwe opcje konfiguracji aplikacji Quarkus.

Konektory

Konfigurację konektora można podać na etapie kompilacji za pomocą pliku właściwości aplikacji:

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

Aby nie komplikować, będziemy używać kolejki wiadomości tylko dla adresu „orders”. Natomiast adres „confirmations” w naszej aplikacji będzie korzystał z kolejki w pamięci.

Punkt końcowy AMQP

Na etapie kompilacji nazwa hosta i numer portu dla punktu końcowego AMQP są nieznane, dlatego należy je wstrzyknąć. Punkt końcowy można określić w configmap, który jest tworzony przez AMQ Online, dlatego zdefiniujemy je za pomocą zmiennych środowiskowych w manifeście aplikacji:

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

Dane uwierzytelniające

Token konta usługi można wykorzystać do uwierzytelnienia naszej aplikacji w OpenShift. W tym celu najpierw należy utworzyć niestandardowy ConfigSource, który będzie odczytywał token uwierzytelniający z systemu plików pod’a:

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

Budowanie i wdrażanie aplikacji

Ponieważ aplikację trzeba skompilować do pliku wykonywalnego, potrzebna będzie maszyna wirtualna GraalVM. Szczegóły dotyczące konfiguracji środowiska można znaleźć w odpowiednich instrukcjach w Przewodniku Quarkus.

Następnie, postępując zgodnie z tamtejszymi instrukcjami, należy pobrać źródła, przeprowadzić budowę i wykonać wdrożenie naszej aplikacji:

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

Po tych poleceniach aplikacja będzie wdrożona, ale nie uruchomi się, dopóki nie skonfigurujemy w AMQ Online potrzebnych zasobów komunikacji.

Konfiguracja systemu komunikacji

Teraz należy określić w systemie komunikacji zasoby, które są potrzebne naszej aplikacji. W tym celu trzeba stworzyć: 1) przestrzeń adresową, aby zainicjować punkt końcowy systemu komunikacji; 2) adres, aby skonfigurować adresy, które wykorzystujemy w aplikacji; 3) użytkownika systemu komunikacji, aby ustawić dane uwierzytelniające klienta.

Przestrzeń adresowa

Obiekt AddressSpace w AMQ Online to zbiór adresów, które wspólnie korzystają z punktów końcowych połączenia oraz polityk uwierzytelniania i autoryzacji. Podczas tworzenia przestrzeni adresowej można określić, jak będą udostępniane punkty końcowe systemu komunikacji:

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

Adresy

Adresy są używane do wysyłania i odbierania wiadomości. Każdy adres ma typ, który określa jego semantykę, a także plan, który określa liczbę zarezerwowanych zasobów. Adres można zdefiniować na przykład w ten sposób:

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

Użytkownik systemu wymiany wiadomości

Aby tylko zaufane aplikacje mogły wysyłać i odbierać wiadomości na twoich adresach, w systemie wymiany wiadomości należy utworzyć użytkownika. Dla aplikacji działających w klastrze klienci mogą być uwierzytelniani za pomocą konta usługi OpenShift. Użytkownika "serviceaccount" można zdefiniować na przykład tak:

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

Uprawnienia do konfiguracji aplikacji

Aby AMQ Online mógł utworzyć configmap, którego użyliśmy do wdrożenia informacji o końcowym punkcie AMQP, należy zdefiniować rolę i powiązanie roli (Role i 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

Jak zastosować konfiguracje

Konfigurację systemu wymiany wiadomości można zastosować w ten sposób:

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

Weryfikacja aplikacji

Aby upewnić się, że aplikacja została uruchomiona, najpierw sprawdźmy, czy odpowiednie adresy zostały utworzone i są aktywne:

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

Następnie sprawdźmy URL trasy aplikacji (po prostu otworzymy ten adres w przeglądarce):

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

W przeglądarce powinno być widać, że bilety okresowo się aktualizują, gdy wiadomości są wysyłane i odbierane przez AMQ Online.

Podsumowując

Stworzyliśmy aplikację Quarkus, która wykorzystuje AMQP do wymiany wiadomości, skonfigurowaliśmy tę aplikację do działania na platformie Red Hat OpenShift, a także wdrożyliśmy jej konfigurację opartą na AMQ Online. Następnie stworzyliśmy manifesty niezbędne do zainicjowania systemu wymiany wiadomości dla naszej aplikacji.

Na tym kończymy serię o Quarkus, ale przed nami wiele nowości i interesujących rzeczy, zostawajcie z nami!

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster