Troca de mensagens orientada para a nuvem na plataforma Red Hat OpenShift utilizando Quarkus e AMQ Online

Olá a todos! Aqui está ele – nosso post final da série sobre Quarkus! (A propósito, assista ao nosso webinar "Este é o Quarkus – um framework Java nativo do Kubernetes". Vamos mostrar como começar "do zero" ou migrar soluções existentes)

Troca de mensagens orientada para a nuvem na plataforma Red Hat OpenShift utilizando Quarkus e AMQ Online

Em anterior neste post, examinamos as ferramentas relevantes que permitem avaliar quantitativamente as melhorias obtidas com a modernização de aplicações Java.

Desde a versão 0.17.0, Quarkus suporta o uso do Advanced Message Queuing Protocol (AMQP), que é um padrão aberto para a transmissão de mensagens de negócios entre aplicações ou organizações.

Red Hat AMQ Online é um serviço construído sobre o projeto aberto EnMasse e implementa um mecanismo de troca de mensagens baseado na plataforma Red Hat OpenShift. Para mais detalhes sobre como ele funciona, veja. aqui (EN). Hoje, mostraremos como combinar AMQ Online e Quarkus para construir um moderno sistema de troca de mensagens na OpenShift, utilizando duas novas tecnologias relacionadas ao processamento de mensagens.

Supõe-se que você já tenha implementado o AMQ Online na plataforma OpenShift (se não, veja o guia de instalação).

Para começar, criaremos uma aplicação Quarkus que será um simples sistema de processamento de pedidos usando troca de mensagens reativa. Esta aplicação incluirá um gerador de pedidos que enviará pedidos para a fila de mensagens em intervalos regulares, bem como um processador de pedidos que lidará com as mensagens da fila e gerará confirmações disponíveis para visualização no navegador.

Após criar a aplicação, mostraremos como integrar a configuração do sistema de troca de mensagens e utilizaremos o AMQ Online para inicializar os recursos necessários nesse sistema.

Aplicação Quarkus

Nossa aplicação Quarkus está em execução na OpenShift e representa uma versão modificada do programa amqp-quickstart. Um exemplo completo da parte do cliente pode ser encontrado aqui.

Gerador de pedidos

O gerador envia monotonamente identificadores crescentes de pedidos para o endereço "orders" a cada 5 segundos.

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

Processador de pedidos

O processador de pedidos é ainda mais simples, basta retornar o identificador de confirmação para o endereço "confirmations".

@ApplicationScoped
public class OrderProcessor {
    @Incoming("orders")
    @Outgoing("confirmations")
    public Integer process(Integer order) {
        // O identificador de confirmação é igual ao dobro do identificador do 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 confirmação

O recurso de confirmação é um ponto final HTTP para listar as confirmações geradas pelo nosso aplicativo.

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

Configuração

Para conectar ao AMQ Online, nosso aplicativo precisará de algumas informações de configuração, a saber: configuração do conector Quarkus, informações do ponto final AMQP e credenciais do cliente. É melhor manter todas as informações de configuração em um só lugar, mas vamos dividi-las para mostrar possíveis opções de configuração do aplicativo Quarkus.

Conectores

A configuração do conector pode ser fornecida no momento da compilação através de um arquivo de propriedades do aplicativo:

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

Para simplificar, usaremos a fila de mensagens apenas para o endereço "orders". O endereço "confirmations" em nosso aplicativo usará uma fila em memória.

Ponto final AMQP

No momento da compilação, o nome do host e o número da porta para o ponto final AMQP são desconhecidos, portanto, eles precisam ser injetados. O ponto final pode ser definido em um configmap criado pelo AMQ Online, por isso vamos defini-los através de variáveis de ambiente no manifesto do aplicativo:

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

Credenciais

O token de conta de serviço pode ser usado para autenticar nosso aplicativo no OpenShift. Para isso, primeiro é necessário criar uma ConfigSource personalizada que lerá o token de autenticação do sistema de arquivos do 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);
    }
}

Compilação e implantação do aplicativo

Como o aplicativo precisa ser compilado em um executável, será necessário ter a máquina virtual GraalVM. Para mais detalhes sobre como configurar o ambiente, consulte as instruções correspondentes em Guia Quarkus.

Em seguida, seguindo as instruções lá, é preciso baixar o código-fonte, compilar e implantar nosso aplicativo:

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

Após esses comandos, o aplicativo estará implantado, mas não iniciará até que configuremos os recursos de mensageria necessários no AMQ Online.

Configuração do sistema de mensageria

Agora precisamos definir os recursos de mensageria que nosso aplicativo requer. Para isso, é necessário criar: 1) um espaço de endereços para inicializar o ponto final do sistema de mensageria; 2) um endereço para configurar os endereços que usamos no aplicativo; 3) um usuário do sistema de mensageria para definir as credenciais do cliente.

Espaço de endereços

O objeto AddressSpace no AMQ Online é um grupo de endereços que compartilham os pontos finais de conexão, assim como as políticas de autenticação e autorização. Ao criar um espaço de endereços, é possível definir como os pontos finais do sistema de mensageria serão fornecidos:

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

Endereços

Os endereços são usados para enviar e receber mensagens. Cada endereço possui um tipo que determina sua semântica, além de um plano que define a quantidade de recursos reservados. Um endereço pode ser definido, por exemplo, assim:

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

Usuário do sistema de mensagens

Para garantir que apenas aplicações confiáveis possam enviar e receber mensagens em seus endereços, é necessário criar um usuário no sistema de mensagens. Para aplicações que rodam em um cluster, os clientes podem ser autenticados usando uma conta de serviço do OpenShift. O usuário "serviceaccount" pode ser definido, por exemplo, assim:

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

Permissões para configuração de aplicativo

Para que o AMQ Online possa criar o configmap que usamos para implantar as informações do ponto final AMQP, é necessário definir um papel e um vínculo de papel (Role e 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

Como aplicar as configurações

As configurações do sistema de mensagens podem ser aplicadas assim:

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

Verificação do aplicativo

Para garantir que o aplicativo foi iniciado, primeiro vamos verificar se os endereços correspondentes foram criados e estão ativos:

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

Em seguida, vamos verificar a URL do caminho do aplicativo (basta abrir esse endereço no navegador):

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

Deve ser visível no navegador que os tickets são atualizados periodicamente à medida que as mensagens são enviadas e recebidas pelo AMQ Online.

Resumindo

Assim, escrevemos um aplicativo Quarkus que utiliza AMQP para troca de mensagens, configuramos este aplicativo para funcionar na plataforma Red Hat OpenShift, e implementamos sua configuração com base na configuração do AMQ Online. Em seguida, criamos os manifestos necessários para iniciar o sistema de mensagens para o nosso aplicativo.

Com isso, encerramos a série sobre Quarkus, mas há muito mais novo e interessante pela frente, fiquem conosco!

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster