最近项目中需要使用到RocketMq来改进某个高并发业务,顺便梳理下最近整合的东西
1、系统环境:
操作系统:Windows 8.1 64位
JDK:1.7以上
2、安装RocketMq
https://github.com/alibaba/RocketMQ/releases
注:保证服务端的安装磁盘要保证有15%的空闲空间,否则默认RocketMq的策略是不接收队列消息
下载好alibaba-rocketmq-3.2.6.tar.gz 之后解压,之后进入bin目录
首先双击运行bin下的mqnamesrv.exe,并出现启动成功的提示,并且不关掉该界面
第二步则打开命令提示符界面输入以下下图命令,完成后不关闭该界面
先开启一个windows终端cmd,进入解压的bin目录,先输入set NAMESRV_ADDR=127.0.0.1:9876
设置环境变量,输入mqbroker
启动broker,保持mqbroker.exe运行,不要关闭这个终端。
这样RocketMq就运行起来了。
3、客户端代码部分
rocketMq发送端代码:
package com.wechat.tool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
public class RocketMqProducer {
private final Logger logger = LoggerFactory.getLogger(RocketMqProducer.class);
private DefaultMQProducer defaultMQProducer;
private String producerGroup;
private String namesrvAddr;
/**
* Spring bean init-method
*/
public void init() throws MQClientException {
// 参数信息
logger.info("DefaultMQProducer initialize!");
logger.info(producerGroup);
logger.info(namesrvAddr);
// 初始化
defaultMQProducer = new DefaultMQProducer(producerGroup);
defaultMQProducer.setNamesrvAddr(namesrvAddr);
defaultMQProducer.setInstanceName(String.valueOf(System.currentTimeMillis()));
defaultMQProducer.start();
logger.info("DefaultMQProudcer start success!");
}
/**
* Spring bean destroy-method
*/
public void destroy() {
defaultMQProducer.shutdown();
}
public DefaultMQProducer getDefaultMQProducer() {
return defaultMQProducer;
}
// ---------------setter -----------------
public void setProducerGroup(String producerGroup) {
this.producerGroup = producerGroup;
}
public void setNamesrvAddr(String namesrvAddr) {
this.namesrvAddr = namesrvAddr;
}
}
该对象的实例初始化与销毁都是由spring来控制,RocketMqProducer需要保持单例,主要是由spring配置文件控制,下面是RocketMqProducer相关配置
<bean id="rocketMqProducer" class="com.wechat.tool.RocketMqProducer"
init-method="init"
destroy-method="destroy"
scope="singleton">
<property name="producerGroup" value="PushConsumer" />
<property name="namesrvAddr" value="127.0.0.1:9876" />
</bean>
springmvc控制层这块主要调用RocketMqProducer单例对象,对RocketMq进行消息队列的发送,下列只列出部分控制层代码
@RequestMapping(value = "/coupon/couponsend.htm")
@ResponseBody()
public Map<String,String> couponsend(){
String sendStatus ="";
String msgId ="";
try{
String msgtext="优惠券领取"+DTUtil.getTodayString4();
Message msg = new Message("PushTopic",
"push",
"coupon"+DTUtil.getNowLongTime(),
msgtext.getBytes());
SendResult result = rocketMqProducer.getDefaultMQProducer().send(msg);
System.out.println("id:" + result.getMsgId() +
" result:" + result.getSendStatus());
msgId = result.getMsgId();
sendStatus=result.getSendStatus()+"";
}catch (Exception e) {
e.printStackTrace();
}
Map<String,String> m=new HashMap<String, String>();
m.put("sendStatus", sendStatus);
m.put("msgId", msgId);
return m;
}
@Autowired
private RocketMqProducer rocketMqProducer;
rocketMq消费者端:
package com.wechat.test;
import java.util.List;
import com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.common.message.MessageExt;
public class PushConsumer {
public static void main(String[] args){
DefaultMQPushConsumer consumer =
new DefaultMQPushConsumer("PushConsumer");
consumer.setNamesrvAddr("127.0.0.1:9876");
try {
//订阅PushTopic下Tag为push的消息
consumer.subscribe("PushTopic", "push");
//程序第一次启动从消息队列头取数据
consumer.setConsumeFromWhere(
ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.registerMessageListener(
new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> list,
ConsumeConcurrentlyContext Context) {
Message msg = list.get(0);
System.out.println(msg.getKeys());
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
}
);
consumer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
消费者开启后就不用关闭
使用Apache JMeter开启100个线程,循环1000次的聚合报告如下
使用Apache JMeter开启200个线程,循环1000次的聚合报告如下