野路子解决微信服务器超时会把接口重新调起n次的方法

问题是这个亚子的,故事啊不对,是事故发生在大半年前,本人是一名微信企业号Java开发程序猿,写了一个上报业绩的小页面,然后把数据汇总一下做个报表。很简单一个小网页。写完之后,最开始用的“微信企业号开发者工具”做的测试,从开始写到最后测试都没问题,但是测上线的候,就 暴漏出问了,我明明只点了一次提交按钮,但是最后存到数据库里数据竟然有两条。

懵了,我手快?点了两次?咋回事,问了前台小哥,

你按钮样式是自己写的吗。

不是,用框架写的。

那你加一个框啥的,手快的像能点两次。

10分钟后。加完了。测试。。。。。

偶尔还是会出这种问题。

继续懵比。

页面加了vconsole。ajax就一次。怎么可能存进去两次。

是我电脑的问题还是csdn的问题,为什么我打字的时候光标在乱跑。懵比。

在懵比(百度)了一上午之后, 发现这种狗问题可能是微信的x5内核的浏览器的问题。其他 大佬对这个问题是这么解释的:

由于微信服务器没有在一定时间内接收到反馈。服务器就认为此次接口调用失败,会自动重新调起一次。(大概就是这么个意思)

野路子解决微信服务器超时会把接口重新调起n次的方法_第1张图片

 

我觉得是csdn的问题,我的光标一直在 乱跑,不行我去记事本里写了 ,然后复制过来8。

微信你这样乱发请求经过我的同意了吗?
热心网友A出招:“这问题简单,你只要在url上加一个参数,叫&connect_redirect=1 ,就行了”
发现救命稻草之后,马上抓住,试了一下。发现,这稻草,不行啊,加了之后还是调起了两次啊。
没办法项目马上上线了。只能找野路子了。
这时候公司内另一个程序猿出招:“就一个insert又不会失败,你就先给他返回个成功,然后在建个线程去存不就完了。”
好主意啊。马上搞,直接写返回语句。结果别说 还真成功了。

野路子解决微信服务器超时会把接口重新调起n次的方法_第2张图片

所以就这样写的:

Thread t1 = getThread("1",platform,response);
t1.start();
json.put("state", "success");
json.put("keyId", paltform.getKeyId());
response.getWriter().println(json);


就这样安安心心的上线了大半年之后。直到上个月,原本安稳的生活,因为一个功能,变得稀烂。

老大说有个需求,就是把我上报的数据,通过接口推到另一个系统里。就叫那个系统为c系统吧。

没问题,简单点一批。给我个接口,写个json调一下不就完事了吗。

还是一样的配方,还是一样的错误。

我点一次推送,他那边收到了两条数据。

懵比。因为推送和直接insert不一样,他是有很大几率推送失败的。原因可能是,用户填写的时候,某些数据填写不完整,或者两个平台数据不统一。反正不成功的概率很大。不能直接返回成功。
野路子解决微信服务器超时会把接口重新调起n次的方法_第3张图片

不能这么搞了。只能继续想(查)办(百)法(度)了。

查了两天之后,毫无进展。这时。我们的高级开发工程师可能是看到了我发际线猛地往后移了一截。然后来问我怎么回事。

给他解释了一番。高级开发工程师给我出了这么个招子。

你可以写个缓存,定个时间戳,把你推送的id加上时间戳做成缓存存起来。

每次次调起接口的时候,判断一下这个时间戳和id是不是在缓存里,同一个时间戳和id如果已经在缓存里了,就视为是微信的第二次第三次自动调起。然后让他滚去死循环。给死循环里写个时间,循环10分钟20分钟的把他释放。这样也不会占太多的内存。

不得不说,不愧是高级开发工程师。思路就是不一样。路子够野。

马上搞了一套,用redis写的缓存。但是我没有写时间戳(懒)。直接用的keyid做的key,结果数据是只有一条了。

但是

前台接不到反馈结果了。

这不行啊,客户们不就认为他一直没有推送成功吗。

又经过了一顿思(百)考(度)了解到。

当微信服务器自己发起第二次请求的时候,他就不会去管第一次请求的返回值了。不管你第一次返回的是什么,都不管,他只会认最后一次,但是最后一次请求,滚到死循环里去了啊。还没这么简单,还要给个赋值。第一次请求成功后,要告诉死循环里的第二次请求,然后让第二次请求把消息反馈给前台。

结果代码是这样的:

Jedis redis = new Jedis("ip地址",6379);//生产环境
redis.auth("mima");
if(redis.exists(keyId)) {
	int count=0;
	while(redis.exists(keyId)) {
		if(keyId.equals(redis.get(keyId))) {
			Thread.sleep(100);
			count++;
		}else if("success".equals(redis.get(keyId))){
			json.put("code", "success");
			break;
		}else if("failed".equals(redis.get(keyId))) {
			json.put("code", "false");
			break;
		}
		if(count>300) {
			break;
		}
	}
		response.getWriter().println(json);
}else {
    redis.setex(keyId, 300,keyId);
    //正常调接口要做的事情
    if("true".equals(success)) {
		//推送成功,更改状态,推送之后,isPush==>1,status==>2,已推送,审批通过状态
		ipfs.changePushStatus(keyId);//更改状态
		json.put("code", "success");
	} else if("inexists".equals(success)) {
		json.put("code", "inexists");
	} else if("false".equals(success)) {
		json.put("code", "false");
	}
}

 

缓存不要立即删除!

缓存不要立即删除!

缓存不要立即删除!

因为我最开始写的是第二次成功之后就马上把缓存删除了(怕占内存),然后就还会一直出这种问题。

所以我最后选择了一种比较懒的方法,写了一个缓存的存活时间,给了5分钟。就是说,同一单在5分钟之内不能重复推送。这样就不会出现推送重复的问题了。问题到现在就已经解决了。路子很野,不是正常思路。但是很有效。

鼓掌!

 

如果看到这篇文章的小伙伴们,有更有效的方法,欢迎留言一起讨论一番。

 

 

你可能感兴趣的:(野路子解决微信服务器超时会把接口重新调起n次的方法)