RocketMq demo

pom文件添加依赖配置

	<dependencies>
		<dependency>
			<groupId>org.apache.rocketmq</groupId>
			<artifactId>rocketmq-client</artifactId>
			<version>4.6.1</version>
		</dependency>

	</dependencies>

简单demo

阻塞方式
Producer

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;

public class Producer {

    public static void main(String[] args) throws Exception {
        DefaultMQProducer producer  =new DefaultMQProducer("first");

        //设置nameServer地址
        producer.setNamesrvAddr("192.168.100.121:9876");
        producer.start();

        //发送topic 信息
        Message msg1 = new Message("myTopic","first 第一条".getBytes());
        Message msg2 = new Message("myTopic","first 第二条".getBytes());
        Message msg3 = new Message("myTopic","first 第三条".getBytes());

        //同步发送消息
        SendResult sendResult1 = producer.send(msg1);
        SendResult sendResult2 = producer.send(msg2);
        SendResult sendResult3 = producer.send(msg3);

        System.out.println(sendResult1);
        System.out.println(sendResult2);
        System.out.println(sendResult3);

        producer.shutdown();
        System.out.println("shut down");
    }
}
SendResult [sendStatus=SEND_OK, msgId=C0A86477000001F6DC6132685A070000, offsetMsgId=C0A8647900002A9F00000000006ADA3B, messageQueue=MessageQueue [topic=myTopic, brokerName=localhost.localdomain, queueId=3], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=C0A86477000001F6DC6132685A9A0001, offsetMsgId=C0A8647900002A9F00000000006ADADD, messageQueue=MessageQueue [topic=myTopic, brokerName=localhost.localdomain, queueId=0], queueOffset=0]
SendResult [sendStatus=SEND_OK, msgId=C0A86477000001F6DC6132685A9F0002, offsetMsgId=C0A8647900002A9F00000000006ADB7F, messageQueue=MessageQueue [topic=myTopic, brokerName=localhost.localdomain, queueId=1], queueOffset=0]
shut down

Consumer

import java.util.List;

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.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;

public class Consumer {

    public static void main(String[] args)throws Exception {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("firstConsumer");

        consumer.setNamesrvAddr("192.168.100.121:9876");

        // 每个consumer 关注一个topic

        // topic 关注的消息的地址
        // 过滤器 * 表示不过滤
        consumer.subscribe("myTopic", "*");

        consumer.registerMessageListener(new MessageListenerConcurrently() {

            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {

                for (MessageExt msg : msgs) {

                    System.out.println(new String(msg.getBody()));;
                }
                // 默认情况下 这条消息只会被 一个consumer 消费到 点对点
                // message 状态修改
                // ack
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.setMessageModel(MessageModel.CLUSTERING);
        consumer.start();
        System.out.println("Consumer 01 start...");
    }
}

异步发送

AsyProducer.java

package oliver.simple;

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;

public class AsyProducer {


    public static void main(String[] args) throws Exception{
        DefaultMQProducer producer  =new DefaultMQProducer("firstProducer");

        //设置nameServer地址
        producer.setNamesrvAddr("192.168.100.121:9876");
        producer.start();

        //发送topic 信息
        Message msg1 = new Message("myTopic","first 第三条".getBytes());

        //异步可靠发送消息//不用等着回馈,采用监听的方式
        producer.send(msg1, new SendCallback() {
            public void onSuccess(SendResult sendResult) {
               // ack 确认机制
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }

            public void onException(Throwable throwable) {
                System.out.println("抛出的异常-->"+throwable);
            }
        });
    }
}

直接发送,有去,但不确认发送成功

SendOneWayProducer.java

package oliver.simple;

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

public class SendOneWayProducer {

    public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException {
        DefaultMQProducer producer  =new DefaultMQProducer("firstProducer");

        //设置nameServer地址
        producer.setNamesrvAddr("192.168.100.121:9876");
        producer.start();

        //发送topic 信息
        Message msg1 = new Message("myTopic","first 第一条".getBytes());

        //单向消息,不确定是否发送成功,没监听
        producer.sendOneway(msg1);

        producer.shutdown();
        System.out.println("shut down");
    }
}

tag过滤发送及接收

TagProducer.java

package oliver.simple;

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;

public class TagProducer {

    public static void main(String[] args) throws Exception{
        DefaultMQProducer producer  =new DefaultMQProducer("firstProducer");

        //设置nameServer地址
        producer.setNamesrvAddr("192.168.100.121:9876");
        producer.start();

        //发送topic 信息
        //tag一般是做过滤的作用,key一般是跟业务做关联
        Message msg1 = new Message("myTopic","tag-a","key-a","first 第三条".getBytes());

        //异步可靠发送消息//不用等着回馈,采用监听的方式
        producer.send(msg1, new SendCallback() {
            public void onSuccess(SendResult sendResult) {
                System.out.println(sendResult);
            }

            public void onException(Throwable throwable) {
                System.out.println("抛出的异常-->"+throwable);
            }
        });
    }
}

TagConsumer.java

package oliver.simple;

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.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;

import java.util.List;

public class TagConsumer {
    public static void main(String[] args)throws Exception {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("firstConsumer");

        consumer.setNamesrvAddr("192.168.100.121:9876");

        // 每个consumer 关注一个topic

        // topic 关注的消息的地址
        // 过滤器 * 表示不过滤
        consumer.subscribe("myTopic","tag-a");

        consumer.registerMessageListener(new MessageListenerConcurrently() {

            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {

                for (MessageExt msg : msgs) {

                    System.out.println(new String(msg.getBody()));;
                }
                // 默认情况下 这条消息只会被 一个consumer 消费到 点对点
                // message 状态修改
                // ack
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.setMessageModel(MessageModel.BROADCASTING);
        consumer.start();
        System.out.println("Consumer tag 02 start...");
    }
}

sql过滤接收

这里注意,broker的配置要更改
去到conf的配置文件里
broker.conf中添加配置

enablePropertyFilter=true

启动broker 加载指定配置文件

../bin/mqbroker -n 192.168.100.121:9876 -c broker.conf 

SqlProducer.java

package oliver.simple;


import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;

public class SqlProducer {

    public static void main(String[] args)throws Exception {

        DefaultMQProducer producer = new DefaultMQProducer("xoxogp");

        // 设置nameserver地址
        producer.setNamesrvAddr("192.168.100.121:9876");
        producer.start();

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

            Message message = new Message("myTopic003", ("xxooxx:" + i ).getBytes());
            message.putUserProperty("age", String.valueOf(i));
            SendResult send = producer.send(message);

            System.out.println(send);
        }
        producer.shutdown();
        System.out.println("已经停机");

    }
}

SqlComsumer.java

package oliver.simple;

import java.util.List;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.MessageSelector;
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.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;

public class SqlComsumer {

    public static void main(String[] args)throws Exception {

        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("xxoo0TAG-B");

        consumer.setNamesrvAddr("192.168.100.121:9876");

        MessageSelector messageSelector = MessageSelector.bySql("age >= 18 and age <= 28");

        consumer.subscribe("myTopic003",messageSelector );

        consumer.registerMessageListener(new MessageListenerConcurrently() {

            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {

                for (MessageExt msg : msgs) {

                    System.out.println(new String(msg.getBody()));;
                }

                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        
        consumer.setMessageModel(MessageModel.CLUSTERING);
        consumer.start();
        System.out.println("Consumer sql-filter start...");
    }
}

发送延迟设置

RocketMQ使用messageDelayLevel可以设置延迟投递
默认配置为

messageDelayLevel	1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
配置

broker.conf中添加配置

messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

这个配置项配置了从1级开始,各级延时的时间,可以修改这个指定级别的延时时间;

时间单位支持:s、m、h、d,分别表示秒、分、时、天;

使用

发送消息时设置

message.setDelayTimeLevel(1); 

保证顺序发送,且顺序消费

队列先天支持FIFO模型,单一生产和消费者下只要保证使用MessageListenerOrderly监听器即可

顺序消费表示消息消费的顺序同生产者为每个消息队列发送的顺序一致,所以如果正在处理全局顺序是强制性的场景,需要确保使用的主题只有一个消息队列。

并行消费不再保证消息顺序,消费的最大并行数量受每个消费者客户端指定的线程池限制。

那么只要顺序的发送,再保证一个线程只去消费一个队列上的消息,那么他就是有序的。

跟普通消息相比,顺序消息的使用需要在producer的send()方法中添加MessageQueueSelector接口的实现类,并重写select选择使用的队列,因为顺序消息局部顺序,需要将所有消息指定发送到同一队列中。

保证有序参与因素

  • FIFO
  • 队列内保证有序
  • 消费线程

ProducerSelectQueue.java
发送到固定query里面

package oliver;

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;

import java.util.List;

public class ProducerSelectQueue {

    public static void main(String[] args)throws Exception {

        DefaultMQProducer producer = new DefaultMQProducer("pgp01");

        producer.setNamesrvAddr("192.168.100.121:9876");


        producer.start();


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

            Message message = new Message("xxoo007", ("hi!" + i).getBytes());

            producer.send(
                    // 要发的那条消息
                    message,
                    // queue 选择器 ,向 topic中的哪个queue去写消息
                    new MessageQueueSelector() {
                        // 手动 选择一个queue
                        public MessageQueue select(
                                // 当前topic 里面包含的所有queue
                                List<MessageQueue> mqs
                                ,
                                // 具体要发的那条消息
                                Message msg

                                // 对应到 send() 里的 args
                                , Object arg) {
                            // TODO Auto-generated method stub

                            // 向固定的一个queue里写消息
                            MessageQueue queue = mqs.get(0);
                            // 选好的queue
                            return queue;
                        }
                    },
                    // 自定义参数
                    0, 2000);
        }

        //	producer.shutdown();
        System.out.println("已经停机");

    }
}

ComsumerSelectQueue.java
接收,线程数设置为1,代码注释为开启多个线程

package oliver;

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class ComsumerSelectQueue {

	public static void main(String[] args)throws Exception {
		
		DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("g02");
		
		consumer.setNamesrvAddr("192.168.100.121:9876");
		
		consumer.subscribe("xxoo007", "*");
		
		
		
		/**
		 * 
		 * 
		 * 
		 * 
		 * MessageListenerConcurrently   并发消费 / 开多个线程
		 * 
		 * 
		 */
//		consumer.registerMessageListener(new MessageListenerConcurrently() {
//
//			public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
//
//				for (MessageExt msg : msgs) {
//
//					System.out.println(new String(msg.getBody()));;
//				}
//				return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
//			}
//		});

		
		/*
		 * 
		 * MessageListenerOrderly 顺序消费 ,对一个queue 开启一个线程,多个queue 开多个线程 
		 * 
		 * 
		 */
		
		
		// 
		// 最大开启消费线程数
		int consumeThreadMax=1;
		consumer.setConsumeThreadMax(consumeThreadMax);
		//  最小线程数
		int consumeThreadMin=1;
		consumer.setConsumeThreadMin(consumeThreadMin);
		consumer.registerMessageListener(new MessageListenerOrderly() {

			public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
				for (MessageExt msg : msgs) {

				System.out.println(new String(msg.getBody()) + " Thread:" + Thread.currentThread().getName());;
			}
			return ConsumeOrderlyStatus.SUCCESS;
			}
		});
		
		consumer.start();
		System.out.println("Consumer g02 start...");
	}
}

事务发送(这里要另外写一篇)

TrancationProducer.java

package oliver.transaction;

import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;

public class TrancationProducer {

    public static void main(String[] args) throws Exception{
        TransactionMQProducer producer = new TransactionMQProducer("transactionProducerGroup");
        producer.setNamesrvAddr("192.168.100.121:9876");
        //回调
        producer.setTransactionListener(new TransactionListener() {
            public LocalTransactionState executeLocalTransaction(Message message, Object o) {
                //执行本地事务
                /*a();
                b();*/
                System.out.println("===============executeLocalTransaction=========");
                System.out.println("msg->"+new String(message.getBody()));
              return  LocalTransactionState.UNKNOW;
//                return LocalTransactionState.COMMIT_MESSAGE;
            }

            public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
                //broker端回调
                System.out.println("===============checkLocalTransaction=========");
                System.out.println("msg->"+new String(messageExt.getBody()));
                return LocalTransactionState.UNKNOW;
//                return LocalTransactionState.ROLLBACK_MESSAGE;
            }


        });
        producer.start();

        producer.sendMessageInTransaction(new Message("transactionProducerTopic","test transaction".getBytes()),null);

        System.out.println("=============test transaction end");
    }

}

分布式系统中的事务可以使用TCC(Try、Confirm、Cancel)、2pc来解决分布式系统中的消息原子性

RocketMQ 4.3+提供分布事务功能,通过 RocketMQ 事务消息能达到分布式事务的最终一致

RocketMQ实现方式

Half Message: 预处理消息,当broker收到此类消息后,会存储到RMQ_SYS_TRANS_HALF_TOPIC的消息消费队列中

检查事务状态: Broker会开启一个定时任务,消费RMQ_SYS_TRANS_HALF_TOPIC队列中的消息,每次执行任务会向消息发送者确认事务执行状态(提交、回滚、未知),如果是未知,等待下一次回调。

超时: 如果超过回查次数,默认回滚消息

TransactionListener的两个方法
executeLocalTransaction

半消息发送成功触发此方法来执行本地事务

checkLocalTransaction

broker将发送检查消息来检查事务状态,并将调用此方法来获取本地事务状态

本地事务执行状态

LocalTransactionState.COMMIT_MESSAGE

执行事务成功,确认提交

LocalTransactionState.ROLLBACK_MESSAGE

回滚消息,broker端会删除半消息

LocalTransactionState.UNKNOW

暂时为未知状态,等待broker回查

参考官网地址

官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值