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事物,messagequeue和messagequeueselector等。
歡迎關注我的公衆號:EQuaker,更多東西等你來拿。