Mensagens baseadas na nuvem do Red Hat OpenShift usando o Quarkus e o AMQ Online

Olá a todos! Aqui está ele - nosso post final da série Quarkus! (A propósito, consulte nosso webinar “Esta é a estrutura Java nativa do Quarkus - Kubernetes . Mostraremos como começar do zero ou transferir soluções prontas)



Em um post anterior, vimos as ferramentas apropriadas com as quais você pode quantificar as melhorias feitas como resultado da modernização do Java formulários.

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

O Red Hat AMQ Online é um serviço criado com base no projeto aberto do EnMasse e implementa um mecanismo de mensagens baseado na plataforma Red Hat OpenShift . Saiba mais sobre como ele funciona, consulte Aqui (para EN) . Hoje, mostramos como combinar o AMQ Online e o Quarkus para criar um sistema de mensagens moderno baseado no OpenShift usando duas novas tecnologias relacionadas ao processamento de mensagens.

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

Para começar, criaremos o aplicativo Quarkus, que será um sistema simples de processamento de pedidos usando mensagens reativas. Esse aplicativo incluirá um gerador de pedidos que envia pedidos para a fila de mensagens com um intervalo fixo, bem como um processador de pedidos que processa mensagens da fila e gera confirmações que podem ser visualizadas no navegador.

Após criar o aplicativo, mostraremos como implementar a configuração do sistema de mensagens e usar o AMQ Online para inicializar os recursos que precisamos nesse sistema.

Quarkus app


Nosso aplicativo Quarkus é executado no OpenShift e é uma versão modificada do amqp-quickstart . Um exemplo completo do lado do cliente pode ser encontrado aqui .

Gerador de pedidos


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

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

Manipulador de pedidos


O processador de pedidos é ainda mais simples, apenas retorna o identificador de confirmação para o endereço "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


Um recurso de confirmação é um terminal HTTP para listar as confirmações geradas por nosso aplicativo.

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

Costumização


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

Conectores


A configuração do conector pode ser fornecida no estágio de compilação usando o arquivo de propriedades do aplicativo:

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

Para não complicar, usaremos a fila de mensagens apenas para o endereço "pedidos". E o endereço "confirmações" em nosso aplicativo usará a fila na memória.

Endpoint AMQP


No estágio de compilação, o nome do host e o número da porta do terminal AMQP são desconhecidos, portanto, eles precisam ser implementados. O nó de extremidade pode ser definido no configmap, criado pelo AMQ Online, portanto, nós os definiremos através das 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 da conta de serviço pode ser usado para autenticar nosso aplicativo no OpenShift. Para fazer isso, você deve primeiro criar um ConfigSource personalizado que leia o token de autenticação do sistema de arquivos 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);
    }
}

Montagem e implantação do aplicativo


Como o aplicativo deve ser compilado em um arquivo executável, é necessária uma máquina virtual GraalVM. Para obter mais informações sobre como configurar um ambiente para isso, consulte as instruções relacionadas no Guia do Quarkus .

Depois, seguindo as instruções, você precisa baixar a fonte, criar 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.

Configuração de mensagens


Agora resta definir os recursos que nosso aplicativo precisa no sistema de mensagens. Para fazer isso, crie: 1) o espaço de endereço para inicializar o terminal do sistema de mensagens; 2) o endereço para configurar os endereços que usamos no aplicativo; 3) o usuário do sistema de mensagens para definir as credenciais do cliente.

Espaço de endereço


O objeto AddressSpace no AMQ Online é um grupo de endereços que compartilham pontos de extremidade de conexão, bem como políticas de autenticação e autorização. Ao criar um espaço de endereço, você pode especificar como os pontos de extremidade do sistema de mensagens 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 define sua semântica, bem como um plano que define o número de recursos 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 enviar e receber mensagens para seus endereços que somente aplicativos confiáveis ​​podiam, você deve criar um usuário no sistema de mensagens. Para aplicativos em execução em um cluster, os clientes podem ser autenticados usando uma conta de serviço OpenShift. O usuário "serviceaccount" pode ser definido, por exemplo, da seguinte maneira:

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 personalizar o aplicativo


Para que o AMQ Online crie o mapa de configuração que usamos para implementar as informações do terminal AMQP, você deve especificar a função e a ligação de função (Role and 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 configurações


Você pode aplicar a configuração de mensagens como esta:

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 aplicativo


Para garantir que o aplicativo tenha sido iniciado, primeiro verificaremos se os endereços correspondentes estão criados e ativos:

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

Em seguida, verifique o URL da rota do aplicativo (basta abrir este endereço no navegador):

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

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

Resumir


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

Isso conclui a série Quarkus, mas há muitas coisas novas e interessantes pela frente, fique conosco!

All Articles