微信开发中的消息排重机制实现

微信公众平台开发时,微信推送消息的机制是推送过来后如果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容量来缓解。

实现代码:
别忘记复写hashcode、equals方法

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;
    }
      省略set和get方法...

}

方案一升级版

方案一的解决并不优雅,而且无法在负载均衡环境下使用。

改进方式是在【方案一】的基础上,使用redis替换List作为存储中介,将DuplicateRemovalMessage对象存储到redis中,存储的key可以用msgId,事件消息可以用FromUserName + CreateTime 拼接,同时给对象设置一个15秒的超时时间,这样就不会有List那种集合存储元素无限增多的情况。

最后

微信推送消息的CreateTime 精确到秒值,这就可能出现一个用户正常操作的情况下触发两条FromUserName 和CreateTime 完全相同的消息,也就是说按照微信文档上提供的排重方法会过滤掉合法数据,我在线上环境遇到过一次。

我们微信公众号开启了获取用户地理位置的功能,用户打开微信后点击菜单进入了某个页面,此时微信后台向我们推送了用户地理位置事件消息和用户点击公众号菜单事件消息,这两个消息的CreateTime 和FromUserName 相同。

所以最后建议做排重的时候,事件消息使用FromUserName + CreateTime+Event三个字段进行排重。

本文最初发布在iteye,由于iteye编辑博客内容提示我有敏感词,可是又不告诉我是哪个敏感词(真2b),无法编辑老文章,所以文章和更新以后都发到这里了。
(全文完)

时间: 2024-08-02 04:39:27

微信开发中的消息排重机制实现的相关文章

C#微信公众号开发系列教程五(接收事件推送与消息排重)

原文:C#微信公众号开发系列教程五(接收事件推送与消息排重) 微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C#微信公众号开发系列教程四(接收普通消息) C#微信公众号开发系列教程五(接收事件推送与消息排重) 在上一篇的博文中讲到,微信的消息可以大体分为两种类型,一种是包括:文本,语音,图片等的普通消息,另一种就是本篇要将的事件类型.包括:关注/

pc-怎么在微信开发中实现智能绑定功能

问题描述 怎么在微信开发中实现智能绑定功能 在pc 端的一个网站 注册了一个账户 扫描下面的二维码 可实现 智能绑定 怎么做啊 急急急 解决方案 其实这个吧,已经有实现过了的,目测小米手环的就是类似的功能(我不是米黑也不是米粉,咱们就事论事说开发),它应该是这样儿来实现的,应用里 有个按钮叫做"微信接入",点击这个按钮,打开微信,自动跳转到微信应用程序里,然后传递一些相关的参数(具体要看微信开放平台给了啥参数,从 里面找到你需要的),获取你在微信里的用户信息,传到后台,进行保存,然后如

php版微信开发之接收消息,自动判断及回复相应消息的方法_php实例

本文实例讲述了php版微信开发之接收消息,自动判断及回复相应消息的方法.分享给大家供大家参考,具体如下: 微信的api现在己经强大到可以随意调用我们网站或指定数据库的内容进行自能回复现推送消息了,这里就来给大家介绍一个微信开发的笔记. 发送1,2,3,7测试相应的消息,菜单模式需要升级为服务号,或者订阅人数超过500以上. 1. 用户发送的消息都是通过你提交的开发者URL来接收,这里订阅号就可以搞定,发送过来的都是xml格式数据,需要解析,代码如下: $data = $GLOBALS["HTTP

关于微信开发中微信连wifi功能的商家主页不能跳转问题

问题描述 关于微信开发中微信连wifi功能的商家主页不能跳转问题 以前一直做着的客户一直都没什么问题.近期新开的两个客户,微信配置跟老客户一样但是到微信连wifi最后一步,点击完成时居然跳转至默认页面.商家主页,连接完成页都设置了却跳转至默认页面了.

刮刮卡效果-在微信开发中遇到了一些问题

问题描述 在微信开发中遇到了一些问题 我们有一个刮刮卡效果,如果这个刮刮效果是第一次在微信的自带浏览器中打开,毫无问题,这是可以刮开的.但是假如我按了物理返回键后,这个刮层是无法刮开的. 但是如果是在浏览器中打开,完全不会有这种情况出现. 解决方案 问题描述的不是太清楚-

微信开发中nonce参数有什么作用

问题描述 微信开发中nonce参数有什么作用 请问在微信公众号开发中,验证数据时,nonce参数有什么作用,因为要验证数据的安全性,timestamp+token+signature感觉已经可以验证了.为什么要加入nonce,听说是为了防伪造,但有timestamp应该可以防伪造了吧?不很不理,希望有人能指点一下,谢谢. 解决方案 nonce是一个随机数 Token验证http://www.weixingon.com/wechat/wechatappdev/2-1-2.php 解决方案二: 新增

微信开发中 jssdk 中 jsapi的返回值如何在php中获取

问题描述 微信开发中 jssdk 中 jsapi的返回值如何在php中获取 var getLocation = document.getElementById('getLocation'); getLocation.onclick = function(){ //使用getLocation接口获取地理位置坐标 wx.getLocation({ success:function(res){ var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var

微信开发中使用js改变title标签中的字符,安卓能改变,ios没有改变

问题描述 微信开发中使用js改变title标签中的字符,安卓能改变,ios没有改变 比如这种,document.title ="新的title名称"但貌似这种类型的写法都不行查了很久的百度没看到确切的解决方法,求大神赐教..

微信开发中定时刷新AccessToken免得access_token失效

微信内嵌H5站一直很火,很多公司也想借助微信的用户群和社交群来做点事情,所以对于各位代码君来说也算是一个研究方向吧. access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存. access_token的存储至少要保留512个字符空间.access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的 access_token失效. 公众号可以使用AppID和AppSecret调用本接口来获取access_tok