rocketmq簡介和使用

1.簡介

rocketmq是一個輕量級,低延時,高可用,支持億級消息處理的消息中間件。rocketmq使用起來方便簡單,具備傳統的消息中間件所不具備的特性,例如低延遲,高負載,事物消息等特性,受到越來越多的開發者喜愛。

1.1 整體架構設計

在這裏插入圖片描述
這裏引用 apache rocketmq官網的圖
1.NameServer
NameServer 提供輕量級的服務發現和路由,支持主從。
生產者和消費者從Name Server獲取對應的讀,寫服務。

2.broker Server
broker server 提供輕量級的TOPIC-queue的形式實現消息的存貯。消息支持push 和pull的模式。

3.producer
消息生產者,producer有個很重要的屬性叫producer group ,一般一個業務一個group,大多數情況下一個生產者實例就已經足夠了,如果想提高系統吞吐率,可以在group相同的前提下,設置instantName,這樣同一個group可以擁有多個實例。
消息的發送支持同步,異步。消息種類在簡單的消息的基礎上,還支持順序消息,事物消息。

4.consumer
消息消費者,消費者也有個重要的屬性叫group,Cosumer裏面可以設置消費線程池的大小。

2. 實例

producer

package com.ly.mq.producer;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.common.RemotingHelper;

import java.util.List;

@Data
@AllArgsConstructor
public class Producer {
    private final String namesrvAddr;
    private DefaultMQProducer producer;

    public void syncProducer(String msg) throws Exception {


        //消息創建需要指定topic ,topic底層可和一個或多個隊列進行綁定,在topic下,還有tag 相當於一個子topic
        Message message =
                new Message("topic_test","TagA"
                ,msg.getBytes(RemotingHelper.DEFAULT_CHARSET));
        SendResult result = producer.send(message);
        System.out.println(result.toString());
        //producer.shutdown();
    }

    public void asyncProducer(String msg) throws Exception {

        Message message =
                new Message("topic_test","TagA"
                        ,msg.getBytes(RemotingHelper.DEFAULT_CHARSET));
        producer.send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.printf("OK %s %s", msg,
                        sendResult.getMsgId());
            }

            @Override
            public void onException(Throwable e) {

            }
        });
        //producer.shutdown();
    }

    public Producer(String namesrvAddr) throws Exception {
        this.namesrvAddr = namesrvAddr;
        producer =
                new DefaultMQProducer("rocketmq_test");
        producer.setNamesrvAddr(namesrvAddr);
        //producer.
        producer.start();
    }

    public void orderProducer() throws Exception {


        for (int i = 0; i < 100; i++) {

            int orderId = i % 10;
            Message message =
                    new Message("topic_test", "TagA"
                            , ("hello ordered message,i:" + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
            SendResult result = producer.send(message, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                    Integer id = (Integer) arg;
                    int index = id % mqs.size();
                    System.out.printf("id:%d,msqs's size:%d,index:%d", id, mqs.size(),index);
                    System.out.println();
                    return mqs.get(index);
                }
            }, orderId);

            System.out.println(result);

            //producer.shutdown();
        }
    }

    public static void main(String[] args) throws Exception {
        String namesrvAddr = "192.168.48.138:9876";
        Producer producer = new Producer(namesrvAddr);
        producer.orderProducer();
        /*for(int i = 0;i<10;i++){
            producer.syncProducer("hello rocketmq,"+i);
            producer.asyncProducer("hello rocketmq,"+i);

        }*/
    }
}

consumer

package com.ly.mq.consumer;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.*;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.common.RemotingHelper;

import java.io.UnsupportedEncodingException;
import java.util.List;

@Data
@AllArgsConstructor
public class Consumer {
    private final String namesrvAddr;

    public void consumer() throws Exception {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_test_group_1");
        consumer.setNamesrvAddr(namesrvAddr);

        //tag支持 || 分割訂閱多個tag,或者以*爲通配符
        consumer.subscribe("topic_test","*");
        //consumer.setConsumeThreadMin();

        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                MessageExt ext = msgs.get(0);
                try {
                    String content = new String(ext.getBody(), RemotingHelper.DEFAULT_CHARSET);
                    System.out.println(String.format("msgid:%s,msgcontent:%s",ext.getMsgId(),content));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();


        Thread.sleep(600000);
    }

    public void consumerOrderly() throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_test_group_1");
        consumer.setNamesrvAddr(namesrvAddr);

        consumer.subscribe("topic_test","TagA");

        //consumer.setConsumeThreadMin();

        consumer.registerMessageListener(new MessageListenerOrderly() {
            @Override
            public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {

                MessageExt messageExt = msgs.get(0);
                try {

                    String content = new String(messageExt.getBody(),RemotingHelper.DEFAULT_CHARSET);
                    System.out.println("thread -number:"+Thread.currentThread().getId()+","
                    +"msgId:"+messageExt.getMsgId()+",content:"+content+",queueId:"+context.getMessageQueue().getQueueId());
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
        consumer.start();


        Thread.sleep(600000);
    }


    public static void main(String[] args) throws Exception {
        String namesrvAddr = "192.168.48.138:9876";
        Consumer consumer = new Consumer(namesrvAddr);
        //consumer.consumer();
        consumer.consumerOrderly();
    }
}

3.總結

rocketmq只支持topic 模式,相對於rabbitmq來說,消息路由的種類會少點,但是topic模式已經支持大多數的使用場景了,而且我們不必關注了隊列的綁定,一般一個group一個生產者實例就已經足夠了,多個消費者訂閱同一個topic,在默認的消費模式下,MessageModel.CLUSTERING多消費者,只會有一個消費者能消費到該消息,可以改成 MessageModel.BROADCASTING ,這樣每個消費者都能消費了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章