`
lief
  • 浏览: 27112 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

微信推送消息排重解决办法

 
阅读更多

 微信公众平台开发时,微信推送消息的机制是推送过来后如果5秒内收不到响应则认为没有推送成功,会再次推送,如果5秒内仍没有收到响应继续推送,总共推送三次。

微信文档原文:

普通消息
1、关于重试的消息排重,推荐使用msgid排重。
2、微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

 

事件推送:
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次

关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。

假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

 

 

我的解决方案:

1.创建判断重复消息的DuplicateRemovalMessage类;

2.把微信推送的消息解析赋值给DuplicateRemovalMessage对象实例

3.用静态变量list当缓存,判断DuplicateRemovalMessage实例是否存在于缓存list中,如果存在则为重复消息,如果不存在则不是重复消息并把消息放到缓存list中。

 

此方案弊端:

1.缓存list会无限增大,所以用setMessageToCache方法限制了list最大容量为1000;

2.解决了list最大容量依然还有弊端,就是两条重复的消息之间如果有超过999个DuplicateRemovalMessage对象依然会判断不准,只能增大list容量来缓解,由于这种情况比较极端,目前远没有那么大业务量,所以暂时这么用着了。

 

大家有什么好的解决方案一起交流,欢迎拍砖。

 

下面是具体实现代码:

注意:DuplicateRemovalMessage别忘记复写hashcode、equals方法 

 

private static final int MESSAGE_CACHE_SIZE = 1000;
	private static List<DuplicateRemovalMessage> MESSAGE_CACHE = new ArrayList<DuplicateRemovalMessage>(MESSAGE_CACHE_SIZE);

	/**
	 * @Description: 判断微信请求是否重复
	 * @return boolean 如果重复返回true
	 */
	public static boolean isDuplicate(Map<String, String> request) {
		String fromUserName = request.get("FromUserName");
		String createTime = request.get("CreateTime");
		String msgId = request.get("MsgId");

		DuplicateRemovalMessage duplicateRemovalMessage = new DuplicateRemovalMessage();

		if (msgId != null) {
			duplicateRemovalMessage.setMsgId(msgId);
		} else {
			duplicateRemovalMessage.setCreateTime(createTime);
			duplicateRemovalMessage.setFromUserName(fromUserName);
		}

		if (MESSAGE_CACHE.contains(duplicateRemovalMessage)) {
			// 缓存中存在,直接pass
			return true;
		} else {
			setMessageToCache(duplicateRemovalMessage);
			return false;
		}
	}
	private static void setMessageToCache(DuplicateRemovalMessage duplicateRemovalMessage) {
		if (MESSAGE_CACHE.size() >= MESSAGE_CACHE_SIZE) {
			MESSAGE_CACHE.remove(0);
		}
		MESSAGE_CACHE.add(duplicateRemovalMessage);
	}

 

 

DuplicateRemovalMessage对象:

 

public class DuplicateRemovalMessage {

	private String MsgId;
	
	private String FromUserName;
	
	private String CreateTime;

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((CreateTime == null) ? 0 : CreateTime.hashCode());
		result = prime * result + ((FromUserName == null) ? 0 : FromUserName.hashCode());
		result = prime * result + ((MsgId == null) ? 0 : MsgId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		DuplicateRemovalMessage other = (DuplicateRemovalMessage) obj;
		if (CreateTime == null) {
			if (other.CreateTime != null)
				return false;
		} else if (!CreateTime.equals(other.CreateTime))
			return false;
		if (FromUserName == null) {
			if (other.FromUserName != null)
				return false;
		} else if (!FromUserName.equals(other.FromUserName))
			return false;
		if (MsgId == null) {
			if (other.MsgId != null)
				return false;
		} else if (!MsgId.equals(other.MsgId))
			return false;
		return true;
	}

	
	public String getMsgId() {
		return MsgId;
	}

	public void setMsgId(String msgId) {
		MsgId = msgId;
	}

	public String getFromUserName() {
		return FromUserName;
	}

	public void setFromUserName(String fromUserName) {
		FromUserName = fromUserName;
	}

	public String getCreateTime() {
		return CreateTime;
	}

	public void setCreateTime(String createTime) {
		CreateTime = createTime;
	}
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("DuplicateRemovalMessage [MsgId=");
		builder.append(MsgId);
		builder.append(", FromUserName=");
		builder.append(FromUserName);
		builder.append(", CreateTime=");
		builder.append(CreateTime);
		builder.append("]");
		return builder.toString();
	}

}

 

 

 

分享到:
评论
4 楼 lief 2018-10-09  
iteye的文章无法编辑,该方案的所有改动和完善在知乎上回答过,参考链接:当微信服务器给我的URL发送多次同一请求,怎样实现排重? - 李一峰的回答 - 知乎
https://www.zhihu.com/question/22685171/answer/68281207
3 楼 lief 2017-11-14  
记错了,刚去看了一眼微信文档,微信推送消息超时的时间是5秒。
2 楼 lief 2017-11-14  
as499745582as 写道
我想问的是,如果判断是重复消息了,要怎么做?返回空吗?这样微信是不会继续发信息了,但是我们之前的请求的回复信息不是也发不给微信服务器吗?这个问题想了很久,没有想到解决的方法, 还请博主指点指点

很抱歉,很久没登录博客,刚刚看到你的回复。我捋一下这个逻辑,微信推送消息被我们识别为重复消息→说明之前我们的系统已经收到过相同的消息,微信重复推送这条消息给我们说明之前推给我们的消息都没有得到回复,这里面最大的可能性就是由于种种原因我们服务器处理消息并返回结果给微信时间超过了3秒,导致了微信重复推送。解决办法就是:1、将微信推送消息的处理代码执行时间控制在3秒之内;2、如果处理微信消息的业务确实无法缩短执行时间了,可以改成异步操作,操作完成后使用【客服消息】接口向用户发送结果(当然必须是服务号才有权限使用该接口)。
1 楼 as499745582as 2017-04-18  
我想问的是,如果判断是重复消息了,要怎么做?返回空吗?这样微信是不会继续发信息了,但是我们之前的请求的回复信息不是也发不给微信服务器吗?这个问题想了很久,没有想到解决的方法, 还请博主指点指点

相关推荐

    SQL SERVER 微信推送消息功能

    实现 SQL SERVER 数据库中的微信推送功能,可以将一些报警消息发送到微信讨论组或者微信订阅号、公众号、服务号,需要有认证的微信订阅号或者微信服务号

    c++通过HTTPS以JSON数据格式微信推送消息

    `weixintest2Dlg.cpp`和`weixintest2Dlg.h`可能是用户界面相关的代码,它们可能实现了在Visual Studio环境中创建一个对话框,允许用户输入或查看与微信推送消息相关的参数。而`weixintest2.cpp`和`weixintest2.h`...

    C#微信公众号开发之接收事件推送与消息排重的方法

    主要介绍了C#微信公众号开发之接收事件推送与消息排重的方法,详细分析了事件推送与消息排重的使用技巧,对微信开发有一定参考借鉴价值,需要的朋友可以参考下

    c#winform开发微信企业号推送各类消息

    在本文中,我们将深入探讨如何使用C# WinForm开发微信企业号消息推送功能。微信企业号是一个为企业内部沟通和管理而设计的平台,它提供了丰富的API接口,允许开发者通过编程方式实现各种消息的推送,包括文本、图片...

    企业微信消息推送,可以推送文本、文本卡片、图片、音视频、投票等消息

    .NET企业微信消息推送,可以推送文本、文本卡片、图片、音视频、投票等消息,其中投票消息需设置企业回调URL,具体可参考https://download.csdn.net/download/niitwj/89661135

    C#企业微信及时消息推送的源码,可持续开发

    结合本案例的标题和描述,我们可以了解到这是一个关于利用C#进行企业微信消息推送的项目,具有高度的实用性,能够帮助企业实现自动化和高效的信息传递。 首先,我们需要理解企业微信的API接口是如何工作的。企业...

    java实现企业微信消息推送

    在企业微信API开发中,Java作为一种广泛使用的编程语言,提供了丰富的库和工具来实现与企业微信接口的交互,实现消息推送功能。以下是一份详细的Java实现企业微信消息推送的知识点详解: 1. **企业微信API概述** ...

    微信推送简单流程图

    根据微信官方文档,个人整理出来的微信推送的一个简单的流程图(仅是个人理解)

    lede-openwrt-微信推送.zip

    自从用了老毛子固件中的微信推送,就再也放弃不了了,由于路由器的性能不够,改换LEDE软路由的门厅,但是LEDE软路由中又没有微信推送相关的功能,实在是太不方便了,于是在网上四处寻找软路由的推送脚本,可惜有关软...

    微信推送例子

    在IT行业中,微信推送是一项常见的功能,特别是在移动应用和企业级服务中,它用于实时向用户或客户发送通知、消息和服务信息。在这个“微信推送例子”中,我们重点关注的是使用C#编程语言实现这一功能的方法。 C#是...

    springboot实现微信公众号模版消息推送

    springboot实现微信公众号模版消息推送,用的是构架:springboot+redis,详细教程:https://blog.csdn.net/chenhongming888/article/details/95173079

    java实现微信公众号模版消息推送

    java二次开发接微信公众号接口,实现根据用户授权,获取用户code,再获取openid,然后向其推送模版消息

    微信公众号每日消息推送天气给女朋友制作教程

    给女朋友做的微信公众号消息每日自动推送天气及纪念日通知教程,该教程为github每日自动线上运行版本。本人亲测妹子很喜欢~女孩子都喜欢这种用心做的东西! 1.最新版本 成品 +源码 +消息模板 (需要自己申请 天行 ...

    thinkphp5.0微信公众号推送消息

    thinkphp 5.0 对接微信公众号,向指定用户发送模板消息

    PHP微信信息推送接口、钉钉推送接口、企业微信推送接口

    php编写 微信信息推送接口、钉钉推送接口、企业微信推送接口

    向企业微信中的指定用户推送消息

    在企业微信API中,向指定用户推送消息是实现企业内部沟通和信息传递的重要功能。这一过程涉及到了几个关键步骤和技术细节,以下将详细介绍这个过程: 首先,我们需要了解**企业微信的accs_token**。accs_token是...

    企业微信发送推送消息完整版

    企业微信发送推送消息是企业与员工、客户进行高效沟通的重要工具。在企业微信的API中,提供了丰富的消息推送功能,包括文本、图片、语音、视频等多种类型的消息。本教程将详细解析如何使用企业微信API实现推送消息,...

    微信推送api借鉴程序

    在IT行业中,微信推送API是开发者们常用的工具,主要用于向微信用户或微信群发送各种类型的消息。这个"微信推送api借鉴程序"显然是一个示例或模板,帮助开发者理解如何有效地利用微信API来推送消息,包括文本、图片...

    dotnet-DotNETCore实现微信公众号被关注时推送消息

    dotnet-DotNETCore实现微信公众号被关注时推送消息dotnet-DotNETCore实现微信公众号被关注时推送消息dotnet-DotNETCore实现微信公众号被关注时推送消息dotnet-DotNETCore实现微信公众号被关注时推送消息dotnet-...

    微信企业号推送消息

    微信企业号推送消息是微信为企业用户提供的通讯工具,它允许企业与员工、客户以及合作伙伴进行高效沟通。在微信企业号中,可以实现主动推送消息、接收消息并自动回复的功能,从而提升企业的内部管理效率和对外服务...

Global site tag (gtag.js) - Google Analytics