RocketMQ入门实战

一.安装与部署

在windows上的安装,可搜索其他博客。并进行环境变量配置。

环境:windows10 + jdk1.8(32 位的会报错,建议64),亲身经历。

二.基础实战

启动mq

1.先启动namespace

RocketMQ入门实战_第1张图片

2.启动broker

RocketMQ入门实战_第2张图片

3。下载一个rocket-console。

 百度云链接:百度网盘 请输入提取码 密码: 7k49

RocketMQ入门实战_第3张图片启动并访问http://127.0.0.1:18080/#/topic

打开主题,新建如下

RocketMQ入门实战_第4张图片

 3.代码实操

创建项目,引入pom


        
            org.apache.rocketmq
            rocketmq-client
            4.4.0
        
   

1.生产者

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.io.UnsupportedEncodingException;

public class MyProducer {

    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException, InterruptedException, MQBrokerException {

        DefaultMQProducer producer = new DefaultMQProducer("my_producer");
        producer.setNamesrvAddr("127.0.0.1:9876");
        producer.start();
        Message mes = new Message("tp_1","测试下rocketmq生产者".getBytes(RemotingHelper.DEFAULT_CHARSET));
        SendResult send = producer.send(mes);
        System.out.println(send);
        producer.shutdown();

    }
}

并启动

 2.消费者拉模式


import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;

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

public class MyPullComsumer {

    public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException, UnsupportedEncodingException {

        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("consumer_0");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        consumer.start();

        Set mes = consumer.fetchSubscribeMessageQueues("tp_1");
        for (MessageQueue m : mes) {
            PullResult reult = consumer.pull(m, "*", 0, 10);
            System.out.println("消息信息:" + m);
            List msgFoundList = reult.getMsgFoundList();
            for(MessageExt ext : msgFoundList){
                System.out.println(ext);
                System.out.println(new String(ext.getBody(),"utf-8"));
            }
        }
        consumer.shutdown();
    }
}

并启动

 消费成功。

3.消费者还有另一种模式为推模式,见下列


import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;

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

public class MyPushComsumer {

    public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException, UnsupportedEncodingException {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumer");
        consumer.setNamesrvAddr("127.0.0.1:9876");

        consumer.subscribe("tp_1","*");

        consumer.setMessageListener(new MessageListenerConcurrently() {
            public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext context) {
                MessageQueue messageQueue = context.getMessageQueue();
                System.out.println(messageQueue);
                for (MessageExt m : list) {
                    try {
                        System.out.println(new String(m.getBody(),"utf-8"));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();

    }
}

并启动,同样的

RocketMQ入门实战_第5张图片

 4.上述描述,都是以生产者同步发送消息为例,生产者还可以异步发送,具体代码如下

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
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.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.io.UnsupportedEncodingException;

public class MyAsynProducer {

    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException, InterruptedException, MQBrokerException {

        DefaultMQProducer producer = new DefaultMQProducer("my_producer");
        producer.setNamesrvAddr("127.0.0.1:9876");
        producer.start();
        for (int i = 0; i < 10; i++) {
            Message mes = new Message("tp_1", ("MQ异步的世界" + i).getBytes("utf-8"));
            producer.send(mes, new SendCallback() {
                public void onSuccess(SendResult sendResult) {
                    System.out.println("发送成功" + sendResult);
                }
                public void onException(Throwable throwable) {
                    System.out.println("发送失败" + throwable.getMessage());
                }
            });
        }
        Thread.sleep(1000);
        producer.shutdown();

    }
}

启动项目,并观察消费者Push模式

 RocketMQ入门实战_第6张图片

 异步发送消息的结果如下。

RocketMQ入门实战_第7张图片

三.延迟队列实战

场景:电商提交一个订单,一个小时后检查此订单状态;定时任务轮询查询数据库状态等。

RocketMQ 支持发送延迟消息,预设值的延迟时间间隔为:1s、 5s、 10s、 30s、 1m、 2m、 3m、 4m、 5m、 6m、 7m、 8m、 9m、 10m、 20m、 30m、 1h、 2h;

在上方 1.生产者 的代码基础上稍加改造即可。先启动  MyPushComsumer 消费者

package Rocket;

import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;

import java.io.UnsupportedEncodingException;

public class MyProducer {

    public static void main(String[] args) throws MQClientException, UnsupportedEncodingException, RemotingException, InterruptedException, MQBrokerException {

        DefaultMQProducer producer = new DefaultMQProducer("my_producer");
        producer.setNamesrvAddr("127.0.0.1:9876");
        producer.start();
        Message mes = new Message("tp_1","测试下rocketmq生产者".getBytes(RemotingHelper.DEFAULT_CHARSET));
        // 延迟队列设置 (1s、 5s、 10s、 30s、 1m、 2m、 3m、 4m、 5m、 6m、 7m、 8m、 9m、 10m、 20m、 30m、 1h、 2h) 18个等级
        // 3 表示的不是3s,而是第三个等级 即10s
        mes.setDelayTimeLevel(3);
        SendResult send = producer.send(mes);
        System.out.println(send);
        producer.shutdown();

    }
}

使用  MyPushComsumer 的方式接受消息,会在十秒后接受到消息;

RocketMQ入门实战_第8张图片

 四.如何确保消息不丢失

消息的产生到消费主要经过3个流程,生产者、broker、消费者。只要在这3处保证消息不丢失即可。

1.生产者

生产者同步发送消息时,会有返回值SendResult 接收,当 sendStatus = SEND_OK 即为发送成功。

sendStatus 有4中状态

RocketMQ入门实战_第9张图片

官方的解释为

SEND_OK:消息发送成功
FLUSH_DISK_TIMEOUT:消息发送成功但是服务器刷盘超时
FLUSH_SLAVE_TIMEOUT:消息发送成功但是服务器同步到slave超时
SLAVE_NOT_AVAILABLE:消息发送成功但是此时slave不可用

代码改造确保消息发送成功,简易版

RocketMQ入门实战_第10张图片

 异步发送消息时需要重写成功方法和异常方法来处理

RocketMQ入门实战_第11张图片

 消费者

消费者再拉取模式下会 返回 ConsumeConcurrentlyStatus.CONSUME_SUCCESS 以表示消息消费成功。

 RocketMQ入门实战_第12张图片

 对于broker 储存 消息来说,消息过来先放入内存,再刷盘刷入磁盘中,只需要保证为同步刷盘方式,刷盘成功才返回即可

在broker 的配置文件broker.conf 中设置 flushDiskType

RocketMQ入门实战_第13张图片

 默认为 ASYNC_FLUSH 异步方式,需要改为同步。

flushDiskType = SYNC_FLUSH

我们可以看到配置文件中有个 brokerRole = ASYNC_MASTER 的配置,此配置是配置broker为主从模式时的刷盘机制。默认为异步。

如果系统为主从模式时,将其master节点配置和slave均改为同步,刷盘是否成功可以及时反馈。

 brokerRole = SYNC_MASTER 

 五.如何确保消息幂等性

可以设置全局 id 持久话入消息表中,设置唯一键来保证幂等性;也可以放入缓存中通过查询缓存来解决;并发操作,可以引入分布式锁。

你可能感兴趣的:(中间件,spring,boot,消息队列)