DEV Community

Cover image for Brighter V10: Configurando RocketMQ
Rafael Andrade
Rafael Andrade

Posted on

Brighter V10: Configurando RocketMQ

Brighter V10 agora inclui suporte ao Apache RocketMQ, oferecendo uma solução robusta para mensageria distribuída em aplicações .NET. Este guia irá orientá-lo passo a passo na configuração e no uso das abordagens Vanilla e Fluent do Brighter.

O que é o RocketMQ?

O Apache RocketMQ é uma plataforma open-source de mensageria e streaming distribuída, com baixa latência, alto desempenho, confiabilidade e capacidade para escala de trilhões de mensagens. Originalmente desenvolvido pelo Alibaba, foi projetado para atender a uma ampla gama de cenários, incluindo comunicação assíncrona, event sourcing e processamento de streams, tornando-o uma excelente escolha para arquiteturas de microsserviços desacopladas e escaláveis.

Requisitos

  • .NET 8 ou superior
  • Podman ou Docker

Para o Brighter Vanilla, você precisará dos seguintes pacotes NuGet:

Para o Brighter Fluent:

Revisão Rápida do Brighter

Antes de mergulhar nos detalhes do RocketMQ, vamos relembrar os principais blocos do Brighter.

Request (Comando/Evento)

As mensagens são classes simples que implementam IRequest.

public class Greeting() : Event(Guid.NewGuid())
{
    public string Name { get; set; } = string.Empty;
}
Enter fullscreen mode Exit fullscreen mode
  • Comandos: Operações destinadas a um único destinatário (ex: SendEmail).
  • Eventos: Notificações transmitidas a múltiplos consumidores (ex: OrderShipped).

Criando um Message Mapper (opcional)

Mappers convertem entre seus objetos .NET e o formato de mensagem do Brighter.

A partir do Brighter V10, essa etapa é opcional.

public class GreetingMapper : IAmAMessageMapper<Greeting>
{
    public Message MapToMessage(Greeting request)
    {
        var header = new MessageHeader();
        header.Id = request.Id; 
        header.TimeStamp = DateTime.UtcNow;
        header.Topic = "greeting.topic"; // O tópico de destino para publicação
        header.MessageType = MessageType.MT_EVENT;

        var body = new MessageBody(JsonSerializer.Serialize(request));
        return new Message(header, body);
    }

    public Greeting MapToRequest(Message message)
    {
        return JsonSerializer.Deserialize<Greeting>(message.Body.Bytes)!;
    }
}
Enter fullscreen mode Exit fullscreen mode

Implementando um Request Handler

Handlers contêm a lógica de negócio para processar mensagens recebidas.

public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
    public override Greeting Handle(Greeting command)
    {
        logger.LogInformation("Olá, {Name}", command.Name);
        return base.Handle(command);
    }
}
Enter fullscreen mode Exit fullscreen mode

Configurando o Brighter com RocketMQ

Passo 1: Configurar a conexão com o RocketMQ

Primeiro, defina os detalhes da conexão com seu cluster RocketMQ.

var connection = new RocketMessagingGatewayConnection(new ClientConfig()
    .SetEndpoints("localhost:8081")  // Endpoint do proxy do docker-compose
    .EnableSsl(false)
    .SetRequestTimeout(TimeSpan.FromSeconds(10))
    .Build());
Enter fullscreen mode Exit fullscreen mode

Importante para desenvolvimento local: Se você estiver executando o RocketMQ localmente, certifique-se de que sua VPN esteja desativada, devido a uma limitação atual do SDK .NET do RocketMQ.

Passo 2: Configurar o Consumidor (Assinaturas)

Registre seus handlers e assinaturas no contêiner de injeção de dependência.

services.AddConsumers(opt =>
{
    opt.Subscriptions = [
        new RocketSubscription<Greeting>(
           subscriptionName: "greeting-subscription", // Qualquer valor
           channelName: "greeting-channel", // Qualquer valor
           routingKey: "greeting", // Nome do tópico
           consumerGroup: "greeting-consumer"
        );
    ];

    opt.DefaultChannelFactory = new RocketMqChannelFactory(new RocketMessageConsumerFactory(connection));
});
Enter fullscreen mode Exit fullscreen mode

Passo 3: Configurar o Produtor (Publicações)

Configure o registro de produtores para permitir o envio de mensagens.

services.AddProduces(opt =>
{
    opt.ProducerRegistry = new ProducerRegistry(new RocketMessageProducerFactory(connection,
        [
            new RocketMqPublication<Greeting>
            {
                Topic = "greeting"
            }
        ]).Create());
});
Enter fullscreen mode Exit fullscreen mode

Observação: O cliente .NET do RocketMQ não cria tópicos automaticamente. Você deve criar o tópico greeting manualmente, conforme demonstrado na configuração do docker-compose abaixo.

Configurando o Brighter Fluent com RocketMQ

A API Fluent do Brighter oferece uma experiência de configuração mais simplificada:

services
    .AddHostedService<ServiceActivatorHostedService>()
    .AddFluentBrighter(brighter => brighter
        .UsingRocketMq(rocket => rocket
            .SetConnection(conn => conn
                .SetClient(c => c
                    .SetEndpoints("localhost:8081")
                    .EnableSsl(false)
                    .SetRequestTimeout(TimeSpan.FromSeconds(10))
                    .Build()))
            .UsePublications(pub => pub
                .AddPublication<GreetingEvent>(p => p
                    .SetTopic("greeting")))
            .UseSubscriptions(sub => sub
                .AddSubscription<GreetingEvent>(s => s
                    .SetSubscriptionName("greeting-sub-name")
                    .SetTopic("greeting")
                    .SetConsumerGroup("greeting-consumer-group")
                    .UseReactorMode()
        )));
Enter fullscreen mode Exit fullscreen mode

Desenvolvimento Local: Executando o RocketMQ com Docker

Use o seguinte arquivo docker-compose.yml para iniciar rapidamente um cluster local do RocketMQ, incluindo um painel de gerenciamento.

services:
  # Nameserver do RocketMQ (Descoberta de Serviço)
  nameserver:
    image: apache/rocketmq
    container_name: rocketmq-nameserver
    ports:
      - "9876:9876"  # Porta do Nameserver
    command: sh mqnamesrv
    healthcheck:
      test: [ "CMD", "sh", "-c", "netstat -an | grep 9876" ]
      interval: 5s
      timeout: 10s
      retries: 10
    environment:
      - JAVA_OPT_EXT=-Xms512m -Xmx512m -Xmn256m -Drocketmq.log.level=DEBUG -Drocketmq.log.root.level=DEBUG

  # Broker do RocketMQ (Armazenamento de Mensagens)
  broker:
    image: apache/rocketmq
    container_name: rocketmq-broker
    ports:
      - "10909:10909"
      - "10911:10911"
      - "10912:10912"
    environment:
      - NAMESRV_ADDR=nameserver:9876
      - BROKER_CLUSTER_NAME=DefaultCluster
      - BROKER_NAME=broker-a
      - BROKER_ID=0
      - AUTO_CREATE_TOPIC_ENABLE=true
      - JAVA_OPT_EXT=-Drocketmq.log.level=DEBUG -Drocketmq.log.root.level=DEBUG
    command: sh mqbroker
    depends_on:
      - nameserver
    healthcheck:
      test: [ "CMD", "sh", "-c", "netstat -an | grep 10911" ]
      interval: 5s
      timeout: 10s
      retries: 10

  proxy:
    image: apache/rocketmq
    container_name: rmqproxy
    depends_on:
      - broker
      - nameserver
    ports:
      - "8081:8081"   # Endpoint HTTP (para API REST)
      - "9877:9877"   # Endpoint gRPC (para clientes)
    environment:
      - NAMESRV_ADDR=nameserver:9876
      - JAVA_OPT_EXT=-Drocketmq.log.level=DEBUG -Drocketmq.log.root.level=DEBUG
    command: sh mqproxy
    healthcheck:
      test: [ "CMD", "sh", "-c", "netstat -an | grep 8081" ]
      interval: 5s
      timeout: 10s
      retries: 10

  # Serviço para criar o tópico no RocketMQ
  create-topic:
    image: apache/rocketmq
    command: >
      sh -c "
            echo 'Aguardando o broker ficar pronto...' &&
            until curl -s http://broker:10911/ &>/dev/null; do
              echo 'Broker ainda não está pronto, tentando novamente em 60s...'
                sleep 60
            done;
            echo 'Broker está ativo. Criando tópicos...' &&

            /home/rocketmq/rocketmq-5.3.3/bin/mqadmin updateTopic -n nameserver:9876 -t greeting -c DefaultCluster -r 1 -w 1 -a +message.type=NORMAL && 
            echo 'Concluído'
        "
    depends_on:
      - broker
      - nameserver
    restart: "no"

  # Painel do RocketMQ (Interface Web – Opcional)
  dashboard:
    image: apacherocketmq/rocketmq-dashboard
    container_name: rocketmq-dashboard
    ports:
      - "8080:8080"
    environment:
      - NAMESRV_ADDR=nameserver:9876
    depends_on:
      - nameserver
      - broker
Enter fullscreen mode Exit fullscreen mode

Acesse o painel do RocketMQ em http://localhost:8080 para monitorar seus tópicos e mensagens.

Limitações Atuais

A integração inicial do Brighter com RocketMQ possui algumas limitações:

  • Modo Push não suportado: Apenas consumo baseado em pull está implementado atualmente.
  • Visibilidade de reenfileiramento: O tempo de visibilidade da mensagem não pode ser ajustado durante o reenfileiramento, devido a um bug no SDK .NET do RocketMQ.

Essas limitações serão corrigidas em futuras versões do SDK.

Conclusão

Agora você está pronto para construir aplicações .NET poderosas e desacopladas usando Brighter e RocketMQ. Este guia forneceu os fundamentos para configurar produtores e consumidores, montar um ambiente de desenvolvimento local e entender como o RocketMQ se compara ao Kafka e ao RabbitMQ em diferentes cenários. Para mais detalhes, consulte a documentação oficial do Brighter e do RocketMQ.

Veja o código completo: https://github.com/lillo42/brighter-sample/tree/v10-rocketmq

Top comments (0)