最近,在公司的测试环境,遇到个问题,每次重启应用重启后,原来消费过的消息又被重复推送了一遍,消费者和生产者代码如下:

package com.tf56.queue.client;

import java.util.concurrent.TimeUnit;

import com.alibaba.rocketmq.client.exception.MQBrokerException;
import com.alibaba.rocketmq.client.exception.MQClientException;
import com.alibaba.rocketmq.client.producer.DefaultMQProducer;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.Message;
import com.alibaba.rocketmq.remoting.exception.RemotingException;
/**
* RocketMQ 生产者工具类
* @author zjhua
*
*/
public class RocketMQProducer { private DefaultMQProducer producer;
private String namesrvAddr;
private String groupName;
private String instanceName; public String getNamesrvAddr() {
return namesrvAddr;
} public void setNamesrvAddr(String namesrvAddr) {
this.namesrvAddr = namesrvAddr;
} public String getGroupName() {
return groupName;
} public void setGroupName(String groupName) {
this.groupName = groupName;
} public String getInstanceName() {
return instanceName;
} public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
} public RocketMQProducer(String namesrvAddr, String groupName,
String instanceName) {
super();
this.namesrvAddr = namesrvAddr;
this.groupName = groupName;
this.instanceName = instanceName;
this.producer = new DefaultMQProducer(groupName); producer.setNamesrvAddr(namesrvAddr);
producer.setInstanceName(instanceName);
producer.setVipChannelEnabled(false); try {
producer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
} /**
* 发送消息工具类
* @param topic
* @param tags
* @param keys
* @param body
* @return
* @throws MQClientException
* @throws RemotingException
* @throws MQBrokerException
* @throws InterruptedException
*/
public SendResult send(String topic, String tags, String keys, byte[] body)
throws MQClientException, RemotingException, MQBrokerException,
InterruptedException {
Message msg = new Message(topic, tags, keys, body);
try {
SendResult sendResult = this.producer.send(msg);
return sendResult;
} catch (MQClientException | RemotingException | MQBrokerException
| InterruptedException e) {
e.printStackTrace();
throw e;
}
} /**
* 发送工具类
* @param topic
* @param tags
* @param keys
* @param body
* @param retryTimes
* @param elapseMS
* @return
*/
public SendResult send(String topic, String tags, String keys, byte[] body,int retryTimes,int elapseMS) {
Message msg = new Message(topic, tags, keys, body);
boolean success = false;
int i = 0;
SendResult sendResult = null;
while (!success && i++ < retryTimes) {
try {
sendResult = this.producer.send(msg);
return sendResult;
} catch (MQClientException | RemotingException | MQBrokerException
| InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(elapseMS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return sendResult;
} public static void main(String[] args) throws MQClientException,
InterruptedException {
RocketMQProducer producer = new RocketMQProducer("10.7.29.121:9876",
"ProducerGroupName", "Producer"); for (int i = 0; i < 10; i++) {
try {
{
SendResult sendResult = producer.send("TopicTestZJH",// topic
"TagA",// tag
"OrderID001",// key
("Hello MetaQ" + i).getBytes());
System.out.println(sendResult);
} {
SendResult sendResult = producer.send("TopicTestYIDU",// topic
"TagB",// tag
"OrderID0034",// key
("Hello MetaQ" + i).getBytes());
System.out.println(sendResult);
}
} catch (Exception e) {
e.printStackTrace();
}
TimeUnit.MILLISECONDS.sleep(1000);
}
/**
* spring bean配置
*/
// <bean id="rocketMQProducer" class="com.tf56.queue.client.RocketMQProducer">
// <constructor-arg name="namesvrAddr" value="10.7.29.121:9876"/>
// <constructor-arg name="groupName" value="ProducerGroupName"/>
// <constructor-arg name="instanceName" value="Producer"/>
// </bean>
}
}

消费端代码:

package tf56.sofa.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
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.client.exception.MQClientException;
import com.alibaba.rocketmq.common.consumer.ConsumeFromWhere;
import com.alibaba.rocketmq.common.message.MessageExt;
import com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; public class RocketMQPushConsumer { private DefaultMQPushConsumer consumer;
private String namesrvAddr;
private String groupName;
private String instanceName;
private String topics; public RocketMQPushConsumer(String namesrvAddr, String groupName, String instanceName,String topics,MessageListenerConcurrently messageListener) {
super();
this.namesrvAddr = namesrvAddr;
this.groupName = groupName;
this.instanceName = instanceName;
this.topics = topics; /**
* 一个应用创建一个Consumer,由应用来维护此对象,可以设置为全局对象或者单例<br>
* 注意:ConsumerGroupName需要由应用来保证唯一
*/
consumer = new DefaultMQPushConsumer(groupName);
consumer.setNamesrvAddr(namesrvAddr);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.setInstanceName(RocketMQPushConsumer.getInstanceName(namesrvAddr));
consumer.setMessageModel(MessageModel.CLUSTERING);
consumer.setVipChannelEnabled(false);
try {
/**
* 订阅指定topic下所有消息<br>
* 注意:一个consumer对象可以订阅多个topic
*/ String[] topicsArr = topics.split(";");
for(int i=0;i<topicsArr.length;i++) {
consumer.subscribe(topicsArr[i], "*");
} consumer.registerMessageListener(messageListener);
} catch (Exception e) {
e.printStackTrace();
return;
}
System.out.println("Consumer Started.");
} /**
* Consumer对象在使用之前必须要调用start初始化,初始化一次即可<br>
*/
public void init() {
try {
consumer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
} private static String getInstanceName(String namesrvAddr) {
return getHostAddress() + namesrvAddr;
} private static String getHostAddress(){
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return "";
} /**
* 当前例子是PushConsumer用法,使用方式给用户感觉是消息从RocketMQ服务器推到了应用客户端。<br>
* 但是实际PushConsumer内部是使用长轮询Pull方式从MetaQ服务器拉消息,然后再回调用户Listener方法<br>
*/
public static void main(String[] args) throws InterruptedException,
MQClientException {
MessageListenerConcurrently messageListener = new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
MessageExt msg = msgs.get(0);
if (msg.getTopic().equals("TopicTestZJH")) {
System.out.println("TopicTestZJH->" + new String(msg.getBody()));
} else if (msg.getTopic().equals("TopicTestYIDU")) {
System.out.println("TopicTestYIDU->" + new String(msg.getBody()));
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
};
RocketMQPushConsumer consumer = new RocketMQPushConsumer("10.7.29.121:9876",
"ConsumerGroupName", "Consumer","TopicTestZJH;TopicTestYIDU",messageListener);
consumer.init();
/**
* spring构造器注入
*/
// <bean id="rocketMQPushConsumer" class="com.tf56.queue.client.RocketMQPushConsumer">
// <constructor-arg name="namesvrAddr" value="10.7.29.121:9876"/>
// <constructor-arg name="groupName" value="ConsumerGroupName"/>
// <constructor-arg name="instanceName" value="Consumer"/>
// <constructor-arg name="topics" value="TopicTestZJH;TopicTestYIDU"/>
// <constructor-arg name="messageListener" ref="messageListener"/>
// </bean>
}
}

补充:问题已经找到了,应该是rocketmq客户端和服务器版本不一致的问题所致,我们公司的环境(由运维统管)使用的是3.2.6,上述出问题的客户端版本使用的是3.6.2.Final。客户端切换成3.2.6版本之后,就没有这个问题了。

参考:http://blog.csdn.net/xyzjl/article/details/54970927

rocketmq消息重复推送的问题的更多相关文章

  1. #研发中间件介绍#异步消息可靠推送Notify

    郑昀 基于朱传志的设计文档 最后更新于2014/11/11 关键词:异步消息.订阅者集群.可伸缩.Push模式.Pull模式 本文档适用人员:研发   电商系统为什么需要 NotifyServer? ...

  2. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制

    2013年10月06日最新整理. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制 微信公共平台消息主动推送接口一直是腾讯的私用接口,相信很多朋友都非常想要用到这个功能. 通过学习 ...

  3. Swift - 本地消息的推送通知(附样例)

    使用UILocalNotification可以很方便的实现消息的推送功能.我们可以设置这个消息的推送时间,推送内容等. 当推送时间一到,不管用户在桌面还是其他应用中,屏幕上方会都显示出推送消息. 1, ...

  4. .NET之微信消息模板推送

    最近在项目中使用到了微信消息模板推送的功能,也就是将对应的消息推送到对应的用户微信上去,前提是你必须要有一个微信公众号并且是付费了的才会有这个功能,还有就是要推送的用户必须是的关注了你的微信公众号的. ...

  5. dwr3实现消息精确推送详细步骤

    最近项目中需要用到推送消息,找了很久终于找到一篇不错的文章,方便以后查看就转载了,也分享给大家,希望能帮到有需要的人. 第一.在项目中引入dwr.jar,然后在web.xml中进行配置,配置如下: & ...

  6. 基于HTTP协议之WEB消息实时推送技术原理及实现

    很早就想写一些关于网页消息实时推送技术方面的文章,但是由于最近实在忙,没有时间去写文章.本文主要讲解基于 HTTP1.1 协议的 WEB 推送的技术原理及实现.本人曾经在工作的时候也有做过一些用到网页 ...

  7. RabbitMQ 延迟队列,消息延迟推送

    目录 应用场景 消息延迟推送的实现 测试结果 应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给 ...

  8. NET SignaiR 实现消息的推送,并使用Push.js实现通知

    一.使用背景 1. SignalR是什么? ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指 ...

  9. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

随机推荐

  1. 命令行方式调用winrar对文件夹进行zip压缩示例代码

    调用winRAR进行压缩 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...

  2. OGeek CTR预估

    特征工程:将所有数据拼接到一起做特征,等到处理完,再按索引拆分数据 1.数据分析 查看标签分布:发现valid与testa.testb的分布相似,说明valid与testa的查询时间比较接近,作为验证 ...

  3. js中两个!!的理解

    在js中经常有两个!!出现,经常让人难以理解 (function () { var a = 10; var b = 20; function add(num1, num2) { var num1 = ...

  4. InstallShield2015制作安装包----------安装过程中修改文件内容

    //修改安装目录下autostart.vbs里的路径 //打开文件 OpenFileMode(FILE_MODE_NORMAL); strPath=INSTALLDIR+"centerAut ...

  5. Nodejs中原生遍历文件夹

    最近在听老师讲的node课程,有个关于把异步变为同步读取文件夹的知识点做一些笔记, 让迭代器逐个自执行.

  6. 笔记 : win8系统中的VM虚拟机的Ubuntu搭建samba服务

    1. 环境准备 (此处使用root超级管理员帐户,执行命令时不用加sudo, 普通帐户需要前面加sudo):  (1)安装好Ubutun虚拟系统后,Ubuntu 的软件源配置文件是 /etc/apt/ ...

  7. C#窗体控件DataGridView常用设置

    在默认情况下,datagridview的显示效果: 1.禁用最后一行空白. 默认情况下,最后一行空白表示自动新增行,对于需要在控件中进行编辑,可以保留 ? 1 dataGridView1.AllowU ...

  8. base64的编码

    计算机中的数据一般是由ascii编码,来存储的, 0---31以及127,表示的是控制字符: 32-126表示的是字符,包括空格,阿拉伯数字,大小写字母: 之后的128个字符,是不可见的字符, 在网络 ...

  9. linux正则

    正则表达式 分两类:  基本正则表达式:BRE  扩展正则表达式:ERE :grep -E, egrep 正则表达式引擎:  采用不同算法,检查处理正则表达式的软件模块       PCRE(Perl ...

  10. Yii2缓存依赖