RocketMQ工具类,并与spring结合

pom.xml:

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

1,生产者:

RocketMQUtils.java:

支持异步,同步,单向发送。

package com.equaker.cache.rocketmq;

import java.util.List;
import java.util.ResourceBundle;

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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.equaker.common.utils.SerializeUtils;

public class RocketMQUtils {

	private static Logger logger = LoggerFactory.getLogger(RocketMQUtils.class);
	private static final String CONFIG_PATH = "config/config";

//	private static final String ROCKETMQ_TOPIC_TOPIC1 = "topic-1";
//	private static final String ROCKETMQ_TAGS_TAGS1 = "tags-1";
//	private static final String ROCKETMQ_PRODUCEGROUP = "produce_group1";
	private static DefaultMQProducer producer = null;

	static {
		try {

			ResourceBundle resourceBundle = ResourceBundle.getBundle(CONFIG_PATH);
			if (resourceBundle == null) {
				throw new IllegalArgumentException("[config.properties] is not found!");
			}

			final String ROCKETMQ_GROUP_NAME = resourceBundle.getString("rocketmq.groupName");

			final String ROCKETMQ_IP = resourceBundle.getString("rocketmq.ip");

			final String ROCKETMQ_RETRYTIMES = resourceBundle.getString("rocketmq.retryTimes");

			final String ROCKETMQ_TIMEOUT = resourceBundle.getString("rocketmq.timeout");

			producer = new DefaultMQProducer(ROCKETMQ_GROUP_NAME);

			producer.setNamesrvAddr(ROCKETMQ_IP);
			producer.start();
			// producer.setRetryTimesWhenSendFailed(Integer.valueOf(ROCKETMQ_RETRYTIMES));
			producer.setRetryTimesWhenSendAsyncFailed(Integer.valueOf(ROCKETMQ_RETRYTIMES));
			producer.setSendMsgTimeout(Integer.valueOf(ROCKETMQ_TIMEOUT));

			logger.info("producer init success >>>");
//			jedisPool = RedisConfig.getInstance().getJedisPool();
		} catch (Exception e) {
			logger.error("producer init fail!!!", e);
		}
	}

	/**
	 * 异步发送消息
	 * @param <T>
	 * 
	 * @param callback 回调函数
	 * @param object   消息体
	 * @param keys     键值对,过滤数据使用
	 */
	public static <T> void asyncPush(String topic, String tags, String keys, SendCallback callback, List<T> objects) {
		
//		for (int i = 0; i < objects.size(); i++) {
//			// Create a message instance, specifying topic, tag and message body.
//			Message msg = new Message(topic, tags, keys, SerializeUtils.serialize(objects.get(i)));
//			try {
//				producer.send(msg, callback);
//				logger.info("send success>>>:");
//			} catch (Exception e) {
//				logger.info("send error>>>:", e);
//			}
//		}

		objects.stream().forEachOrdered(p -> {
			Message msg = new Message(topic, tags, keys, SerializeUtils.serialize(p));
			try {
				producer.send(msg, callback);
				logger.info("send success>>>:");
			} catch (Exception e) {
				logger.info("send error>>>:", e);
			}
		});
	}

	/**
	 * 同步发送消息
	 * @param <T>
	 * 
	 * @param keys   键值对,过滤数据使用
	 * @param object 消息体
	 */
	public static <T> void syncPush(String topic, String tags, String keys,  List<T> objects) {

//		 Integer retLength = 0;// 消息推送成功 总数
//		for (int i = 0; i < objects.size(); i++) {
//			Message msg = new Message(topic, tags, keys, SerializeUtils.serialize(objects.get(i)));
//			try {
//				SendResult sendResult = producer.send(msg);
//				logger.info("send success>>>:" + sendResult.getMsgId());
//				retLength++;
//			} catch (Exception e) {
//				logger.info("send error>>>:", e);
//			}
//		}
		
		objects.stream().forEachOrdered(p->{
			Message msg = new Message(topic, tags, keys, SerializeUtils.serialize(p));
			try {
				SendResult sendResult = producer.send(msg);
				logger.info("send success>>>:" + sendResult.getMsgId());
			} catch (Exception e) {
				logger.info("send error>>>:", e);
			}
		});
		
		//return retLength;
	}

	/**
	 * 同步发送消息
	 * @param <T>
	 * 
	 * @param keys   键值对,过滤数据使用
	 * @param object 消息体
	 */
	public static <T> void onewayPush(String topic, String tags, String keys,  List<T> objects) {
//		for (int i = 0; i < objects.size(); i++) {
//			Message msg = new Message(topic, tags, keys, SerializeUtils.serialize(object[i]));
//			try {
//				producer.sendOneway(msg);
//				logger.info("send success>>>:");
//			} catch (Exception e) {
//				logger.info("send error>>>:", e);
//			}
//		}
		
		objects.stream().forEachOrdered(p->{
			Message msg = new Message(topic, tags, keys, SerializeUtils.serialize(p));
			try {
				producer.sendOneway(msg);
				logger.info("send success>>>:");
			} catch (Exception e) {
				logger.info("send error>>>:", e);
			}
		});
		
	}

}

config.properties:

#### rocketMQ ####
rocketmq.groupName=produce_group1
rocketmq.ip=*:*
rocketmq.retryTimes=2
rocketmq.timeout=5000

消息生产者的配置如上,网上有生产者与spring结合,在需要的地方通过注入的方式使用,个人感觉没有必要,而且容易限制producer,毕竟生产者是包含produce group,topic,tags等信息的。本身只起到一个推送消息的作用,同redis的消息队列(左进右出,和发布订阅模式)类似。

 

2,消费者:

消费者应该是处于阻塞阶段的程序,需要时刻检测队列是否还有数据。所以需要与spring结合,把他的生命周期交给spring管理。

1,首先需要编写一个消息处理类,实现MessageListenerConcurrently接口(或者MessageListenerOrderly,一个单线程,顺序读取,另一个则是异步)。

MessageListenerImpl.java:

package com.equaker.cache.rocketmq;

import java.util.List;

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 com.equaker.common.utils.SerializeUtils;

public class MessageListenerImpl implements MessageListenerConcurrently {

	@Override
	public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
		for(MessageExt msg : msgs) {
            //在这里进行相应的业务逻辑,这里直接进行打印
        	System.out.println(SerializeUtils.deserialize(msg.getBody()));
        	//System.out.println(new String(msg.getBody()));
        }
        System.out.println("*******************");
		return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
	}

}

接下来配置 rocketmq 提供的默认消息消费者:DefaultMQPushConsumer

applicationContext.xml:

<!-- rocketmq 消费者配置 -->
    <bean id="messageListeners" class="com.equaker.cache.rocketmq.MessageListenerImpl"></bean>
    <!-- 导入Spring配置文件 -->
    <bean id="rocketmqConsumer" class="org.apache.rocketmq.client.consumer.DefaultMQPushConsumer" init-method="start" destroy-method="shutdown">
        <property name="consumerGroup" value="consume1"/>
<!--         <property name="instanceName"> -->
<!--             <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> -->
<!--                 <property name="targetClass"> -->
<!--                     <value>com.xx.utils.RunTimeUtil</value> -->
<!--                 </property> -->
<!--                 <property name="targetMethod"> -->
<!--                     <value>getRocketMqUniqeInstanceName</value> -->
<!--                 </property> -->
<!--             </bean> -->
<!--         </property> -->
        <property name="namesrvAddr" value="你的外网地址:port"/>
        <property name="messageListener" ref="messageListeners"/>
        <property name="subscription">
            <map>
                <!-- 进行topic-1的订阅-->
                <entry key="topic-1" value="*" />
            </map>
        </property>
    </bean>

配置完毕。

3,测试:

启动spring项目,会发现rocketmq 的broker.log会有日志显示:

,此时编写produce测试类:

AppTest1.java:

package org.equaker.cache;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;

import com.equaker.cache.rocketmq.RocketMQUtils;

public class AppTest1 {

	public static void main(String[] args) {
		
		List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
		
		for (int i = 0; i < 5; i++) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("name", "@EQuaker-" + i);
			list.add(map);
		}
		
		RocketMQUtils.asyncPush("topic-1", "tags-1", "keys-1", new SendCallback() {

			@Override
			public void onSuccess(SendResult sendResult) {
				System.out.println("messageid: "+sendResult.getMsgId());
			}

			@Override
			public void onException(Throwable e) {
				// TODO Auto-generated method stub

			}
		}, list);
		
//		int length = RocketMQUtils.syncPush("topic-1", "tags-1", "keys-1", map);
//		System.out.println(length);
		
		
	}

}

运行如如下:

produce-console:

consume-tomcat-console:

番外篇:

其实 rocketmq 的消费者模式,一共有两种,MessageModel.CLUSTERING(集群模式), MessageModel.BROADCASTING(广播模式)。字面上就可以理解了。

  • 集群模式:一个ConsumerGroup中的Consumer实例平均分摊消费消息。例如某个Topic有9条消息,其中一个ConsumerGroup有3个实例(可能是3个进程,或者3台机器),那么每个实例只消费其中部分,消费完的消息不能被其他实例消费。
  • 广播模式:发布订阅模式了解一下,订阅同一个topic的所有消费者都会收到相同信息。

另外,消费者 模式是集群模式。如想修改为 广播模式,

consumer.setMessageModel(MessageModel.BROADCASTING);

 

》》》》》》》》》》》》》》》》》》》

暂时这么多了,以后会继续研究rocketmq事物,messagequeue和messagequeueselector等。

欢迎关注我的公众号:EQuaker,更多东西等你来拿。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值