Todos os produtos
Search
Central de documentação

Simple Message Queue (formerly MNS):Fan out messages from one producer to multiple consumers

Última atualização: Jun 27, 2026

O Simple Message Queue (SMQ, anteriormente MNS) oferece suporte a um padrão combinado de tópico e fila: um tópico distribui cada mensagem publicada para várias filas via push, e os consumidores recuperam as mensagens de suas próprias filas privadas por pull. Este tutorial implementa essa arquitetura de distribuição (fan-out) usando o SDK do SMQ para Java.

Nota

Este tutorial utiliza o SDK para Java. Para SDKs em outras linguagens, consulte Referência para SDKs da Nova Versão (Recomendado).

Comparação de modelos de mensagens

O SMQ fornece dois modelos básicos de mensagens. A escolha ideal depende de como os consumidores recebem as mensagens, da possibilidade de expor seus endpoints e da necessidade de entrega seletiva.

Modelo

Funcionamento

Visibilidade do consumidor

Filtragem de mensagens

Mais indicado para

Baseado em fila

Um cliente envia mensagens para uma fila. Vários consumidores recuperam as mensagens por pull, mas cada mensagem vai para apenas um consumidor.

Endpoints permanecem privados

Não suportado

Distribuição de tarefas ponto a ponto

Baseado em tópico

Um cliente publica mensagens em um tópico. O SMQ envia mensagens via push para todos os consumidores inscritos.

Endpoints devem ser expostos

Suportado via filtros de assinatura

Notificações push em tempo real

Combinado (este tutorial)

Um cliente publica em um tópico. O tópico envia mensagens via push para várias filas. Cada consumidor recupera as mensagens de sua própria fila por pull.

Endpoints permanecem privados

Suportado via filtros de assinatura

Distribuição (fan-out) com consumidores privados

O padrão combinado é adequado para cenários em que uma mensagem precisa alcançar vários consumidores cujos endpoints não podem ser expostos — por exemplo, consumidores executando dentro de uma rede privada.

Cenário de exemplo: Um sistema de processamento de pedidos publica cada novo pedido em um tópico. Filas separadas alimentam os serviços de atendimento, análise e notificação. Cada serviço recupera os pedidos de sua própria fila de forma independente, sem expor um endpoint de entrada.

Como funciona

O padrão combinado conecta um tópico a várias filas por meio de assinaturas. Uma assinatura atua como uma fila virtual: ela recebe uma cópia de cada mensagem publicada no tópico, e os consumidores recuperam as mensagens dela por pull exatamente como fariam de uma fila comum.

A configuração segue estas etapas:

  1. Crie um tópico e uma fila por consumidor.

  2. Inscreva cada fila no tópico. O endpoint da fila torna-se o destino da assinatura.

  3. O produtor publica uma mensagem no tópico.

  4. O SMQ copia a mensagem para todas as filas inscritas.

  5. Cada consumidor recupera sua cópia de sua própria fila por pull.

消息流

Como os consumidores recuperam as mensagens das filas por pull em vez de recebê-las via push, seus endpoints nunca ficam expostos ao SMQ ou uns aos outros.

Pré-requisitos

Antes de começar, certifique-se de ter:

Instale a dependência Java

Adicione a dependência do SDK do SMQ ao arquivo pom.xml do seu projeto Java:

<dependencies>
    <dependency>
        <groupId>com.aliyun.mns</groupId>
        <artifactId>aliyun-sdk-mns</artifactId>
        <version>1.1.9.2</version>
    </dependency>
</dependencies>

Referência da API CloudPullTopic

O SDK para Java 1.1.8 introduziu a classe CloudPullTopic, que encapsula o padrão combinado de tópico e fila. Crie um objeto CloudPullTopic por meio do MNSClient:

// Full form: create queues automatically with a queue metadata template
public CloudPullTopic createPullTopic(
    TopicMeta topicMeta,
    Vector<String> queueNameList,
    boolean needCreateQueue,
    QueueMeta queueMetaTemplate
)

// Short form: use existing queues (no automatic creation)
public CloudPullTopic createPullTopic(
    TopicMeta topicMeta,
    Vector<String> queueNameList
)

Parâmetro

Descrição

topicMeta

Metadados do tópico (nome, propriedades).

queueNameList

Lista de nomes de filas. Cada fila recebe uma cópia de toda mensagem publicada.

needCreateQueue

Indica se as filas listadas em queueNameList devem ser criadas. Defina como true para criá-las automaticamente.

queueMetaTemplate

Modelo de metadados de fila aplicado a todas as filas criadas automaticamente (por exemplo, tempo de espera de polling).

Publique e consuma mensagens

O exemplo abaixo usa CloudPullTopic para configurar a distribuição, publicar uma mensagem e recuperá-la por pull em três filas separadas.

package doc;

import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.MNSClient;
import com.aliyun.mns.client.CloudPullTopic;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.model.QueueMeta;
import com.aliyun.mns.model.TopicMeta;
import com.aliyun.mns.model.TopicMessage;
import com.aliyun.mns.model.RawTopicMessage;
import com.aliyun.mns.model.Message;
import com.aliyun.mns.common.ServiceException;
import com.aliyun.mns.common.ClientException;
import java.util.Vector;

public class DemoTopicMessageBroadcast {
    public static void main(String[] args) {

        // Initialize the client with your AccessKey ID, AccessKey Secret, and endpoint.
        CloudAccount account = new CloudAccount(
            ServiceSettings.getMNSAccessKeyId(),
            ServiceSettings.getMNSAccessKeySecret(),
            ServiceSettings.getMNSAccountEndpoint());
        MNSClient client = account.getMNSClient();

        // Define three consumer queues.
        Vector<String> consumerNameList = new Vector<String>();
        String consumerName1 = "consumer001";
        String consumerName2 = "consumer002";
        String consumerName3 = "consumer003";
        consumerNameList.add(consumerName1);
        consumerNameList.add(consumerName2);
        consumerNameList.add(consumerName3);

        // Set long polling to 30 seconds for the auto-created queues.
        QueueMeta queueMetaTemplate = new QueueMeta();
        queueMetaTemplate.setPollingWaitSeconds(30);

        try {
            // --- Producer: create a topic and publish a message ---

            String topicName = "demo-topic-for-pull";
            TopicMeta topicMeta = new TopicMeta();
            topicMeta.setTopicName(topicName);

            // createPullTopic creates the topic, creates the three consumer queues,
            // and subscribes each queue to the topic — all in one call.
            CloudPullTopic pullTopic = client.createPullTopic(
                topicMeta, consumerNameList, true, queueMetaTemplate);

            // Publish a raw message to the topic. SMQ copies it into all subscribed queues.
            String messageBody = "broadcast message to all the consumers:hello the world.";
            TopicMessage tMessage = new RawTopicMessage();
            tMessage.setBaseMessageBody(messageBody);
            pullTopic.publishMessage(tMessage);

            // --- Consumers: pull the message from each queue ---

            CloudQueue queueForConsumer1 = client.getQueueRef(consumerName1);
            CloudQueue queueForConsumer2 = client.getQueueRef(consumerName2);
            CloudQueue queueForConsumer3 = client.getQueueRef(consumerName3);

            // popMessage(30) waits up to 30 seconds for a message (long polling).
            Message consumer1Msg = queueForConsumer1.popMessage(30);
            if (consumer1Msg != null) {
                System.out.println("consumer1 received: "
                    + consumer1Msg.getMessageBodyAsRawString());
            } else {
                System.out.println("consumer1 queue is empty");
            }

            Message consumer2Msg = queueForConsumer2.popMessage(30);
            if (consumer2Msg != null) {
                System.out.println("consumer2 received: "
                    + consumer2Msg.getMessageBodyAsRawString());
            } else {
                System.out.println("consumer2 queue is empty");
            }

            Message consumer3Msg = queueForConsumer3.popMessage(30);
            if (consumer3Msg != null) {
                System.out.println("consumer3 received: "
                    + consumer3Msg.getMessageBodyAsRawString());
            } else {
                System.out.println("consumer3 queue is empty");
            }

            // Clean up: delete the topic, its subscriptions, and all associated queues.
            pullTopic.delete();

        } catch (ClientException ce) {
            System.out.println("Network error between the client and SMQ. "
                + "Check your network and DNS settings.");
            ce.printStackTrace();
        } catch (ServiceException se) {
            se.printStackTrace();
        }

        client.close();
    }
}

Verifique o resultado

Após executar o exemplo, confirme se cada consumidor recebeu a mensagem. Saída esperada:

consumer1 received: broadcast message to all the consumers:hello the world.
consumer2 received: broadcast message to all the consumers:hello the world.
consumer3 received: broadcast message to all the consumers:hello the world.

Se uma fila exibir "queue is empty", a mensagem pode ainda não ter sido entregue. Aumente o tempo limite de popMessage ou verifique se o tópico e as assinaturas foram criados corretamente.

Explicação do código

Etapa

O que acontece

Inicializar CloudAccount

Autentica com seu AccessKey ID, AccessKey Secret e endpoint do SMQ.

Chamar createPullTopic

Cria o tópico, cria as três filas de consumidores e inscreve cada fila no tópico.

Chamar publishMessage

Publica uma mensagem bruta (RawTopicMessage) no tópico. O SMQ a copia para todas as filas inscritas.

Chamar popMessage(30)

Cada consumidor recupera sua cópia por pull com um tempo limite de long polling de 30 segundos.

Chamar pullTopic.delete()

Exclui o tópico, suas assinaturas e todas as filas associadas.

O exemplo publica uma mensagem bruta ( RawTopicMessage ). Analise mensagens brutas com getMessageBodyAsRawString() . Se você usar Base64TopicMessage , analise com getMessageBodyAsString() .

Próximos passos