关于MNS消息发送和接收的实现问题

我在使用MNS发送消息时,用的是阿里云的MNS。一些问题大都可以在官方文档上找到。

消息服务MNS提供了两种API接口,一种是队列接口,一种是主题接口

队列接口适用于点对点的消息收发,当接收消息时,需要应用端自行轮询获取消息(拉模式)。

主题接口适用于一对多的消息收发,应用端只需要在某个地址上启动监听,服务端就会主动将消息推送过去(推模式)。

1,其实使用两种方式都有自己的利弊,不然提供两种方式也就没有什么区别了。

2,队列模型保证消息至少会被消费一次, 支持多个生产者和消费者并发操作同一个消息队列。消费消息时尽量做到先进先出,正是因为分布式消息队列的一些特性并不能保证你能按照消息的发送顺序消费消息,如果你的业务必需先进先出, 建议在消息中加入序号信息以便消费消息后进行重新排序。

3,主题模型支持服务端主动将消息推送给用户指定的回调地址(Endpoint),消除用户程序不必要的轮询和资源消耗。
主题模型保证通知消息按照指定的策略推送给用户,支持多个消息发布者并发操作同一个主题。主题模式支持一对多广播消息,一条通知消息可以同时被多个订阅者接收和消费。

我这里主要说下实现方法:

一、队列接口

1.创建队列

public class CreateQueueDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        String queueName = "TestQueue";
        QueueMeta meta = new QueueMeta(); //生成本地QueueMeta属性,有关队列属性详细介绍见https://help.aliyun.com/document_detail/27476.html
        meta.setQueueName(queueName);  // 设置队列名
        meta.setPollingWaitSeconds(15);
        meta.setMaxMessageSize(2048L);
        try {
            CloudQueue queue = client.createQueue(meta);
        } catch (ClientException ce)
        {
            System.out.println("Something wrong with the network connection between client and MNS service."
                   + "Please check your network and DNS availablity.");
            ce.printStackTrace();
        } catch (ServiceException se)
        {
            se.printStackTrace();
            logger.error("MNS exception requestId:" + se.getRequestId(), se);
            if (se.getErrorCode() != null) {
                if (se.getErrorCode().equals("QueueNotExist"))
                {
                    System.out.println("Queue is not exist.Please create before use");
                } else if (se.getErrorCode().equals("TimeExpired"))
                {
                    System.out.println("The request is time expired. Please check your local machine timeclock");
                }
            /*
            you can get more MNS service error code from following link:
            https://help.aliyun.com/document_detail/mns/api_reference/error_code/error_code.html
            */
            }
        } catch (Exception e)
        {
            System.out.println("Unknown exception happened!");
            e.printStackTrace();
        }
        client.close();  // 程序退出时,需主动调用client的close方法进行资源释放
    }
}

当然,你必须有阿里云提供的相关的key、参数和密钥。

2.发送消息

public class ProducerDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        try {
            CloudQueue queue = client.getQueueRef("TestQueue");
            Message message = new Message();
            message.setMessageBody("I am test message ");
            Message putMsg = queue.putMessage(message);
            System.out.println("Send message id is: " + putMsg.getMessageId());
        } catch (ClientException ce)
        {
            System.out.println("Something wrong with the network connection between client and MNS service."
                   + "Please check your network and DNS availablity.");
            ce.printStackTrace();
        } catch (ServiceException se)
        {
            se.printStackTrace();
            logger.error("MNS exception requestId:" + se.getRequestId(), se);
            if (se.getErrorCode() != null) {
                if (se.getErrorCode().equals("QueueNotExist"))
                {
                    System.out.println("Queue is not exist.Please create before use");
                } else if (se.getErrorCode().equals("TimeExpired"))
                {
                    System.out.println("The request is time expired. Please check your local machine timeclock");
                }
            /*
            you can get more MNS service error code from following link:
            https://help.aliyun.com/document_detail/mns/api_reference/error_code/error_code.html
            */
            }
        } catch (Exception e)
        {
            System.out.println("Unknown exception happened!");
            e.printStackTrace();
        }
        client.close();  // 程序退出时,需主动调用client的close方法进行资源释放
    }
}


3.接受和删除消息

public class ConsumerDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        try{
            CloudQueue queue = client.getQueueRef("TestQueue");
            Message popMsg = queue.popMessage();
            if (popMsg != null){
                System.out.println("message handle: " + popMsg.getReceiptHandle());
                System.out.println("message body: " + popMsg.getMessageBodyAsString());
                System.out.println("message id: " + popMsg.getMessageId());
                System.out.println("message dequeue count:" + popMsg.getDequeueCount());
                //删除已经取出消费的消息
                 queue.deleteMessage(popMsg.getReceiptHandle());
                    System.out.println("delete message successfully.\n");
            }
            else{
                System.out.println("message not exist in TestQueue.\n");
            }
        } catch (ClientException ce)
        {
            System.out.println("Something wrong with the network connection between client and MNS service."
                    + "Please check your network and DNS availablity.");
            ce.printStackTrace();
        } catch (ServiceException se)
        {
            se.printStackTrace();
            logger.error("MNS exception requestId:" + se.getRequestId(), se);
            if (se.getErrorCode() != null) {
                if (se.getErrorCode().equals("QueueNotExist"))
                {
                    System.out.println("Queue is not exist.Please create before use");
                } else if (se.getErrorCode().equals("TimeExpired"))
                {
                    System.out.println("The request is time expired. Please check your local machine timeclock");
                }
            /*
            you can get more MNS service error code from following link:
            https://help.aliyun.com/document_detail/mns/api_reference/error_code/error_code.html
            */
            }
        } catch (Exception e)
        {
            System.out.println("Unknown exception happened!");
            e.printStackTrace();
        }
        client.close();
    }
}


4.删除队列

public class DeleteQueueDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        try{
            CloudQueue queue = client.getQueueRef("TestQueue");
            queue.delete();
        } catch (ClientException ce)
        {
            System.out.println("Something wrong with the network connection between client and MNS service."
                    + "Please check your network and DNS availablity.");
            ce.printStackTrace();
        } catch (ServiceException se)
        {
            se.printStackTrace();
        } catch (Exception e)
        {
            System.out.println("Unknown exception happened!");
            e.printStackTrace();
        }
        client.close();
    }
}


二、主题方式

1.创建主题

public class CreateTopicDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        String topicName = "TestTopic";
        TopicMeta meta = new TopicMeta();
        meta.setTopicName(topicName);
        try {
            CloudTopic topic = client.createTopic(meta);
        } catch (Exception e)
            e.printStackTrace();
            System.out.println("create topic error, " + e.getMessage());
        }
        client.close();
    }
}


2.发送消息

public class PublishMessageDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        CloudTopic topic = client.getTopicRef("TestTopic");
        try {
            TopicMessage msg = new Base64TopicMessage(); //可以使用TopicMessage结构,选择不进行Base64加密
            msg.setMessageBody("hello world!");
            msg.setMessageTag("filterTag"); //设置该条发布消息的filterTag
            msg = topic.publishMessage(msg);
            System.out.println(msg.getMessageId());
            System.out.println(msg.getMessageBodyMD5());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("subscribe error");
        }
        client.close();
    }
}


3.创建订阅、接受消息

public class ConsumerDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        try{
            CloudTopic topic = client.getTopicRef("TestTopic");
            ubscriptionMeta subMeta = new SubscriptionMeta();
            subMeta.setSubscriptionName("TestSub");
            subMeta.setNotifyContentFormat(SubscriptionMeta.NotifyContentFormat.SIMPLIFIED);
            subMeta.setEndpoint(topic.generateQueueEndpoint("TestQueue");
            subMeta.setFilterTag("filterTag");
            topic.subscribe(subMeta);
            //订阅相关主题
            CloudQueue queue = client.getQueueRef("TestQueue");
            Message popMsg = queue.popMessage();
            if (popMsg != null){
                System.out.println("message handle: " + popMsg.getReceiptHandle());
                System.out.println("message body: " + popMsg.getMessageBodyAsString());
                System.out.println("message id: " + popMsg.getMessageId());
                System.out.println("message dequeue count:" + popMsg.getDequeueCount());
                //删除已经取出消费的消息
                 queue.deleteMessage(popMsg.getReceiptHandle());
                    System.out.println("delete message successfully.\n");
            }
            else{
                System.out.println("message not exist in TestQueue.\n");
            }
        } catch (ClientException ce)
        {
            System.out.println("Something wrong with the network connection between client and MNS service."
                    + "Please check your network and DNS availablity.");
            ce.printStackTrace();
        } catch (ServiceException se)
        {
            se.printStackTrace();
            logger.error("MNS exception requestId:" + se.getRequestId(), se);
            if (se.getErrorCode() != null) {
                if (se.getErrorCode().equals("QueueNotExist"))
                {
                    System.out.println("Queue is not exist.Please create before use");
                } else if (se.getErrorCode().equals("TimeExpired"))
                {
                    System.out.println("The request is time expired. Please check your local machine timeclock");
                }
            /*
            you can get more MNS service error code from following link:
            https://help.aliyun.com/document_detail/mns/api_reference/error_code/error_code.html
            */
            }
        } catch (Exception e)
        {
            System.out.println("Unknown exception happened!");
            e.printStackTrace();
        }
        client.close();
    }
}
4.取消订阅、删除zhu't

队列模型保证消息至少会被消费一次, 支持多个生产者和消费者并发操作同一个消息队列。

消费消息时尽量做到先进先出,正是因为分布式消息队列的一些特性并不能保证你能按照消息的发送

顺序消费消息,如果你的业务必需先进先出, 建议在消息中加入序号信息以便消费消息后进行重新排

序。

队列模型保证消息至少会被消费一次, 支持多个生产者和消费者并发操作同一个消息队列。

消费消息时尽量做到先进先出,正是因为分布式消息队列的一些特性并不能保证你能按照消息的发送

顺序消费消息,如果你的业务必需先进先出, 建议在消息中加入序号信息以便消费消息后进行重新排

序。

队列模型保证消息至少会被消费一次, 支持多个生产者和消费者并发操作同一个消息队列。

消费消息时尽量做到先进先出,正是因为分布式消息队列的一些特性并不能保证你能按照消息的发送

顺序消费消息,如果你的业务必需先进先出, 建议在消息中加入序号信息以便消费消息后进行重新排

序。

队列模型保证消息至少会被消费一次, 支持多个生产者和消费者并发操作同一个消息队列。

消费消息时尽量做到先进先出,正是因为分布式消息队列的一些特性并不能保证你能按照消息的发送

顺序消费消息,如果你的业务必需先进先出, 建议在消息中加入序号信息以便消费消息后进行重新排

序。

public class DeleteTopicDemo {
    public static void main(String[] args) {
        CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint");
        MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全
        CloudTopic topic = client.getTopicRef("TestTopic");
        try {
            topic.unsubscribe("TestSub");
            topic.delete();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("delete topic error");
        }
        client.close();
    }
}

这个几乎是官网的案例。

但是只要按照这样的顺序和思路写一定不会有问题的。

在使用Spring的时候多使用注入方式。

所以考虑到这个,一半会将这些东西的配置信息写在XML里边。如

    <bean id="queueMeta" class="com.aliyun.mns.model.QueueMeta">
        <property name="queueName" value="${queueName}"/>
        <property name="pollingWaitSeconds" value="15"/>
        <property name="maxMessageSize" value="2048"/>
    </bean>


  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风华正茂少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值