Хмарно-орієнтований обмін повідомленнями на платформі Red Hat OpenShift з використанням Quarkus та AMQ Online

Всім привіт! Ось і він – наш останній пост із серії про Quarkus! (До речі, дивіться наш вебінар «Це Quarkus – Kubernetes native Java фреймворк». Покажемо, як розпочати «з нуля» або перенести готові рішення)

Хмарно-орієнтований обмін повідомленнями на платформі Red Hat OpenShift з використанням Quarkus та AMQ Online

В попередньому Пост ми розглянули відповідні інструменти, за допомогою яких можна кількісно оцінити покращення, отримані в результаті модернізації Java-додатків.

Починаючи з версії 0.17.0, Кваркус підтримує використання Advanced Message Queuing Protocol (AMQP), який є відкритим стандартом передачі бізнес-повідомлень між додатками чи організаціями.

Red Hat AMQ Online - Це сервіс, побудований на основі відкритого проекту EnMasse та реалізуючий механізм обміну повідомлень на базі платформи Red Hat OpenShift. Докладніше про те, як він влаштований, див. тут (EN). Сьогодні ми покажемо, як об'єднати AMQ Online та Quarkus, щоб побудувати сучасну систему обміну повідомленнями на базі OpenShift з використанням двох нових технологій, пов'язаних із обробкою повідомлень.

Передбачається, що ви вже розгорнули AMQ Online на платформі OpenShift (якщо ні, див. посібник зі встановлення).

Для початку ми створимо додатки Quarkus, яка буде простою системою обробки замовлень з використанням реактивного обміну повідомленнями. Ця програма буде включати генератор замовлень, що відправляє замовлення в чергу повідомлень з фіксованим інтервалом, а також обробник замовлень, який оброблятиме повідомлення з черги і формуватиме підтвердження, доступні для перегляду в браузері.

Після створення програми ми покажемо, як впроваджувати в нього конфігурацію системи обміну повідомленнями та задіямо AMQ Online, щоб ініціалізувати на цій системі необхідні нам ресурси.

Додаток Quarkus

Наш Quarkus-додаток виконується на OpenShift і є модифікованою версією програми amqp-quickstart. Повний приклад клієнтської частини можна знайти тут.

Генератор замовлень

Генератор кожні 5 секунд просто монотонно відправляє ідентифікатори замовлень, що ростуть, на адресу «orders».

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

Обробник замовлень

Обробник замовлень ще простіше, він лише повертає ідентифікатор підтвердження на адресу «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;
    }
}

Ресурси підтвердження

Ресурс підтвердження – це кінцева точка HTTP для лістингу сформованих в результаті роботи нашого додатка підтвердження.

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

Налаштування

Для підключення до AMQ Online нашому додатку знадобляться деякі конфігураційні дані, а саме: конфігурація Quarkus-конектора, відомості про кінцеву точку AMQP та клієнтські облікові дані. Краще, звичайно, тримати всі конфігураційні дані в одному місці, але ми спеціально розділимо їх, щоб показати можливі варіанти налаштування програми Quarkus.

Коннектори

Конфігурацію конектора можна надати на етапі компіляції за допомогою файлу властивостей програми:

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

Щоб не ускладнювати, ми будемо використовувати чергу повідомлень лише для адреси orders. А адреса «confirmations» у нашому додатку використовуватиме чергу в пам'яті.

Кінцева точка AMQP

На етапі компіляції ім'я хоста і номер порту кінцевої точки AMQP невідомі, тому їх потрібно впровадити. Кінцеву точку можна встановити в configmap, який створюється AMQ Online, тому ми визначимо їх через змінні середовища в маніфесті програми:

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

Облікові дані

Маркер облікового запису сервісу можна використовувати для автентифікації нашої програми OpenShift. Для цього треба спочатку створити користувальницький ConfigSource, який читатиме маркер аутентифікації з файлової системи 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);
    }
}

Складання та розгортання програми

Оскільки програму потрібно скомпілювати у виконуваний файл, знадобиться віртуальна машина GraalVM. Докладніше про те, як налаштувати для цього оточення, див. Quarkus Guide.

Потім, дотримуючись наведених там інструкцій, треба завантажити вихідник, провести складання та виконати розгортання нашого додатку:

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

Після цих команд програма буде розгорнута, але не запуститься доти, доки ми не налаштуємо в AMQ Online необхідні нам ресурси обміну повідомленнями.

Налаштування системи обміну повідомленнями

Тепер залишилося встановити в системі обміну повідомленнями ресурси, які потрібні нашому додатку. Для цього необхідно створити: 1) адресний простір, щоб ініціалізувати кінцеву точку системи обміну повідомленнями; 2) адресу, щоб налаштувати адреси, які ми використовуємо у додатку; 3) користувача системи обміну повідомленнями, щоб встановити облікові дані клієнта.

Простір адрес

Об'єкт AddressSpace в AMQ Online – це група адрес, які спільно використовують кінцеві точки підключення, а також політики автентифікації та авторизації. При створенні простору адрес можна задати, як саме будуть надаватися кінцеві точки системи обміну повідомленнями:

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

Адреси

Адреси використовуються для надсилання та отримання повідомлень. Кожна адреса має тип, який визначає його семантику, а також план, який задає кількість резервованих ресурсів. Адреса можна визначити, наприклад, ось так:

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

Користувач системи обміну повідомленнями

Щоб надсилати та отримувати повідомлення на ваші адреси могли тільки довірені програми, в системі обміну повідомленнями необхідно створити користувача. Для програм, які працюють на кластері, клієнтів можна аутентифікувати за допомогою облікового запису OpenShift. Користувача «serviceaccount» можна визначити, наприклад, так:

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

Дозволи для налаштування програми

Щоб AMQ Online міг створити configmap, який ми використовували для впровадження відомостей про кінцеву точку AMQP, необхідно задати роль та прив'язку ролі (Role та 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

Як застосувати конфігурації

Застосувати конфігурацію системи обміну повідомленнями можна так:

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

Верифікація програми

Щоб переконатися, що програма запустилася, насамперед перевіримо, чи створилися та чи активні відповідні адреси:

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

Потім перевіримо URL маршруту програми (просто відкриємо цю адресу у браузері):

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

У браузері має бути видно, що тикети періодично оновлюються в міру того, як повідомлення надсилаються та приймаються AMQ Online.

Підводимо підсумки

Отже, ми написали програму Quarkus, яка використовує AMQP для обміну повідомленнями, налаштували цю програму для роботи на платформі Red Hat OpenShift, а також впровадили її конфігурацію на основі конфігурації AMQ Online. Потім ми створили маніфести, необхідні для ініціалізації системи обміну повідомленнями під нашим додатком.

На цьому ми завершуємо серію про Quarkus, але попереду багато нового та цікавого, залишайтеся з нами!

Джерело: habr.com

Додати коментар або відгук