RoketMQ 顺序消息

2023-07-30  本文已影响0人  程序猿TT

顺序消息DEMO

1. 准备

ProductOrder

public class ProductOrder {
    private String orderId;
    private String type;

    public ProductOrder(String orderId, String type) {
        this.orderId = orderId;
        this.type = type;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "ProductOrder{" +
                "orderId='" + orderId + '\'' +
                ", type='" + type + '\'' +
                '}';
    }
}

OrderType

public enum OrderType {
    ORDER_CREATE, ORDER_PAYMENT, ORDER_FINISHED
}

Producer

public class OrderProducer {
    private static final List<ProductOrder> orderList = new ArrayList<>();

    static {
        orderList.add(new ProductOrder("ORDER_001", OrderType.ORDER_CREATE.name()));
        orderList.add(new ProductOrder("ORDER_001", OrderType.ORDER_PAYMENT.name()));
        orderList.add(new ProductOrder("ORDER_001", OrderType.ORDER_FINISHED.name()));
        orderList.add(new ProductOrder("ORDER_002", OrderType.ORDER_CREATE.name()));
        orderList.add(new ProductOrder("ORDER_002", OrderType.ORDER_PAYMENT.name()));
        orderList.add(new ProductOrder("ORDER_002", OrderType.ORDER_FINISHED.name()));
        orderList.add(new ProductOrder("ORDER_003", OrderType.ORDER_CREATE.name()));
        orderList.add(new ProductOrder("ORDER_003", OrderType.ORDER_PAYMENT.name()));
        orderList.add(new ProductOrder("ORDER_003", OrderType.ORDER_FINISHED.name()));
        orderList.add(new ProductOrder("ORDER_004", OrderType.ORDER_CREATE.name()));
        orderList.add(new ProductOrder("ORDER_004", OrderType.ORDER_PAYMENT.name()));
        orderList.add(new ProductOrder("ORDER_004", OrderType.ORDER_FINISHED.name()));
    }

    public static void main(String[] args) throws Exception {
        //创建一个消息生产者,并设置一个消息生产者组
        DefaultMQProducer producer = new DefaultMQProducer("default-producer");
        //指定 NameServer 地址
        producer.setNamesrvAddr("localhost:9876");
        //初始化 Producer,整个应用生命周期内只需要初始化一次
        producer.start();

        for (int i = 0; i < orderList.size(); i++) {
            //获取当前order
            ProductOrder order = orderList.get(i);
            //创建一条消息对象,指定其主题、标签和消息内容
            Message message = new Message(
                    /* 消息主题名 */
                    "topicTest_1",
                    /* 消息标签 */
                    order.getType(),
                    /* 消息KEY */
                    order.getOrderId(),
                    /* 消息内容 */
                    (order.toString()).getBytes(StandardCharsets.UTF_8)
            );

            //发送消息并返回结果 使用hash选择策略
            SendResult sendResult = producer.send(message, new SelectMessageQueueByHash(), order.getOrderId());

            System.out.println("product: 发送状态:" + sendResult.getSendStatus() + ",存储queue:" + sendResult.getMessageQueue().getQueueId() + ",orderID:" + order.getOrderId() + ",type:" + order.getType());
        }

        // 一旦生产者实例不再被使用则将其关闭,包括清理资源,关闭网络连接等
        producer.shutdown();
    }
}

Consumer

public class OrderConsumer {
    private static final Random random = new Random();

    public static void main(String[] args) throws Exception {
        //创建一个消息消费者,并设置一个消息消费者组
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer_group_order");
        //指定 NameServer 地址
        consumer.setNamesrvAddr("localhost:9876");
        //设置 Consumer 第一次启动时从队列头部开始消费还是队列尾部开始消费
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //订阅指定 Topic 下的所有消息
        consumer.subscribe("topicTest_1", "*");

        //注册消费的监听 这里注意顺序消费为MessageListenerOrderly
        consumer.registerMessageListener((MessageListenerOrderly) (list, context) -> {
            //默认 list 里只有一条消息,可以通过设置参数来批量接收消息
            if (list != null) {
                for (MessageExt ext : list) {
                    try {
                        try {
                            //模拟业务逻辑处理中...
                            TimeUnit.SECONDS.sleep(random.nextInt(10));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        //重试次数
                        int retryTimes = ext.getReconsumeTimes();
                        //获取接收到的消息
                        String message = new String(ext.getBody(), RemotingHelper.DEFAULT_CHARSET);
                        //获取队列ID
                        int queueId = context.getMessageQueue().getQueueId();
                        //打印消息
                        System.out.println("Consumer-线程名称=[" + Thread.currentThread().getId() + "],重试次数:[" + retryTimes + "],接收queueId:[" + queueId + "],接收时间:[" + new Date().getTime() + "],消息=[" + message + "]");

                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 模拟异常
            int num = random.nextInt(10);
            if (num % 3 == 0) {
                System.out.println("系统出现异常,阻塞当前队列...");
                return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
            }
            return ConsumeOrderlyStatus.SUCCESS;
        });

        // 消费者对象在使用之前必须要调用 start 初始化
        consumer.start();
        System.out.println("消息消费者已启动");
    }
}
上一篇 下一篇

猜你喜欢

热点阅读