Mensagens nativas da nuvem na plataforma Red Hat OpenShift usando Quarkus e AMQ Online

Olá a todos! Aqui está – nosso último post da série Quarkus! (A propósito, assista ao nosso webinar “Este é o Quarkus – framework Java nativo do Kubernetes”. Mostraremos como começar do zero ou transferir soluções prontas)

Mensagens nativas da nuvem na plataforma Red Hat OpenShift usando Quarkus e AMQ Online

В anterior Neste post, vimos as ferramentas relevantes que podem ser utilizadas para quantificar as melhorias obtidas com a modernização de aplicações Java.

Desde a versão 0.17.0, quarks suporta o uso do Advanced Message Queuing Protocol (AMQP), que é um padrão aberto para transferência de mensagens comerciais entre aplicativos ou organizações.

Red Hat AMQ on-line é um serviço construído com base em um projeto de código aberto EnMasse e implementação de um mecanismo de mensagens baseado em plataforma Red Hat OpenShift. Para mais detalhes sobre como funciona, consulte aqui (PT). Hoje mostraremos como combinar AMQ Online e Quarkus para construir um sistema de mensagens moderno baseado em OpenShift usando duas novas tecnologias de mensagens.

Supõe-se que você já tenha implantado o AMQ Online na plataforma OpenShift (caso contrário, consulte Guia de instalação).

Para começar, criaremos um aplicativo Quarkus que será um sistema simples de processamento de pedidos usando mensagens reativas. Esta aplicação incluirá um gerador de pedidos que envia pedidos para uma fila de mensagens em um intervalo fixo, bem como um processador de pedidos que processará as mensagens da fila e gerará confirmações visíveis no navegador.

Depois de criarmos o aplicativo, mostraremos como incorporar a configuração do sistema de mensagens no aplicativo e usar o AMQ Online para provisionar os recursos necessários no sistema.

Aplicativo Quarkus

Nosso aplicativo Quarkus roda em OpenShift e é uma versão modificada do programa amqp-início rápido. Um exemplo completo do lado do cliente pode ser encontrado aqui.

Gerador de pedidos

O gerador simplesmente envia monotonicamente IDs de pedidos crescentes para o endereço de “pedidos” a cada 5 segundos.

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

Processador de pedidos

O manipulador de pedidos é ainda mais simples, apenas retorna um ID de confirmação para o endereço de “confirmações”.

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

Recursos de confirmação

O recurso de confirmação é um endpoint HTTP para listar as confirmações geradas pela nossa aplicação.

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

Fixação

Para se conectar ao AMQ Online, nosso aplicativo precisará de alguns dados de configuração, a saber: configuração do conector Quarkus, informações do endpoint AMQP e credenciais do cliente. É claro que é melhor manter todos os dados de configuração em um só lugar, mas iremos separá-los deliberadamente para mostrar as opções possíveis de configuração do aplicativo Quarkus.

Conectores

A configuração do conector pode ser fornecida em tempo de compilação usando um arquivo de propriedades do aplicativo:

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

Para simplificar, usaremos apenas uma fila de mensagens para o endereço de “pedidos”. E o endereço de “confirmações” em nossa aplicação utilizará uma fila na memória.

Ponto de extremidade AMQP

Em tempo de compilação, o nome do host e o número da porta do endpoint AMQP são desconhecidos, portanto, devem ser injetados. O endpoint pode ser definido no configmap criado pelo AMQ Online, portanto iremos defini-lo através de variáveis ​​de ambiente no manifesto da aplicação:

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 da conta de serviço pode ser usado para autenticar nosso aplicativo no OpenShift. Para fazer isso, primeiro você deve criar um ConfigSource personalizado que lerá o token de autenticação do sistema de arquivos do 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);
    }
}

Construir e implantar o aplicativo

Como a aplicação deve ser compilada em um arquivo executável, é necessária uma máquina virtual GraalVM. Para obter detalhes sobre como configurar um ambiente para isso, consulte as instruções correspondentes em Guia Quarkus.

Então, seguindo as instruções ali fornecidas, você precisa baixar o código-fonte, construir 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 será implantado, mas não será iniciado até que configuremos os recursos de mensagens necessários no AMQ Online.

Configurando o sistema de mensagens

Agora só falta definir os recursos que nossa aplicação necessita no sistema de mensagens. Para fazer isso, é necessário criar: 1) um espaço de endereço para inicializar o terminal do sistema de mensagens; 2) endereço para configurar os endereços que utilizamos na aplicação; 3) Mensagens ao usuário para definir credenciais do cliente.

Espaço de endereço

Um objeto AddressSpace no AMQ Online é um grupo de endereços que compartilham pontos de extremidade de conexão e políticas de autenticação e autorização. Ao criar um espaço de endereço, é possível especificar como os terminais do sistema de mensagens serão expostos:

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

Os endereços são usados ​​para enviar e receber mensagens. Cada endereço possui um tipo, que determina sua semântica, bem como um plano, que especifica a quantidade de recursos a serem reservados. O endereço pode ser determinado, por exemplo, assim:

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

Usuário de mensagens

Para garantir que apenas aplicativos confiáveis ​​possam enviar e receber mensagens em seus endereços, você deve criar um usuário no sistema de mensagens. Para aplicativos executados em um cluster, os clientes podem ser autenticados usando uma conta de serviço 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 configurar o aplicativo

Para que o AMQ Online crie o configmap que usamos para incorporar as informações do endpoint AMQP, Role e RoleBinding devem ser definidos:

---
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 configurações

Você pode aplicar a configuração do sistema de mensagens 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 de aplicação

Para ter certeza de que a aplicação foi iniciada, 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 "Not yet ready"; sleep 5; done

Então vamos verificar a URL da rota da aplicação (basta abrir este endereço no navegador):

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

O navegador deve mostrar que os tickets são atualizados periodicamente à medida que as mensagens são enviadas e recebidas pelo AMQ Online.

Resumindo

Portanto, escrevemos um aplicativo Quarkus que usa AMQP para mensagens, configuramos o aplicativo para ser executado na plataforma Red Hat OpenShift e implementamos sua configuração com base na configuração AMQ Online. Em seguida, criamos os manifestos necessários para inicializar o sistema de mensagens do nosso aplicativo.

Isso conclui a série sobre Quarkus, mas tem muita coisa nova e interessante pela frente, fique ligado!

Fonte: habr.com

Adicionar um comentário