微信退费出现超时的处理

最近一家客户频繁反映,患者退费总是失败,导致意见比较大。于是我特意去查看了错误日志,退费出现连接超时,一天总共就四笔退费,每笔都出了问题。之前其他客户偶尔也有反馈,查看日志发现与当时的网络出现中断有很大关系,但这次只要退费就失败肯定是有问题的。

既然是超时了,优先考虑是不是超时时间设置太短了。查了下代码,用的第三方库,退费超时时间用的缺省值10秒,想想也不是很短,微信支付平台肯定不会需要这么长时间才能处理一笔业务,要不然就没法用了,于是就没从这里着手。

先是怀疑现场网络有问题,也写了个批处理,不停ping腾讯的服务器并打印日志。代码如下:

@echo off 
:loop  
ping -n 3 api.mch.weixin.qq.com >>d:\ping.log  
echo %date%-%time%>>d:\ping.log
timeout /T 3
goto loop 

每隔五秒,发起3次ping操作,打印到日志中然后停2秒。结果发现并没有出现网络中断的情况,想想也是,哪里那么凑巧,退费时网络就挂了,其他时间正常?

后台服务程序的错误日志打印出了以下堆栈:System.Net.WebException: The operation has timed out
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()  ......  拷贝出来先百度,倒是有人针对这个超时的问题做了比较详细的分析,给出了解决方案,例如keepalive要设置成false,增加System.Net.ServicePointManager.DefaultConnectionLimit = 200;增加System.GC.Collect();等等,挨个试了一下,换到现场去,当时能用,过段时间又挂了。还试过把证书重新导入了一下,也是当时成功,后来又不行。

既然每次都超时,那我写个winform的程序测试一下吧。放到现场,这个程序也失败,报连接超时。想着之前在哪里看到过,说调用腾讯平台的api最好使用腾讯云的DNS,不管对不对,先试试。换DNS后,居然测试程序不超时了。难道这是真相?心里也不信,付款的api是同一个域名,就从来没出过超时的问题,DNS解析还管你是不是退费?让同事测试一笔退费,说好了,那先暂且用着,估计还是要出问题的,果然下午又打电话来说退费又不能用。

我赶紧远程过去看,果然日志中又打出了超时的错误,再试试winform程序,居然连接正常。好吧,至少排除了一点,不是由于网络环境导致的问题,至少没有防火墙设置了规则进行拦截。之前我针对付款成功,退款失败的现象有过分析,二者使用的域名相同,但是退款需要使用双向证书,是不是有防火墙拦截了?于是我又回过头来考虑了一下,难不成真的就是超时了?假设一笔退款交易真的要10秒以上,那为什么其他客户不出问题?暂时也没有其他思路,先改一下超时时间的设置吧。

由于业务代码正在增加其他功能,不想恢复一个之前的版本进行修改,就改一下那个开源的第三方库。它的退款函数有一个参数是超时时间的设置,有缺省值10秒,我在调用时并没有传递这个参数。于是我就改了一下这个缺省值变为30秒,编译后放到现场。其实这个地方是有问题的,后面再说。

换了dll后,当时测试是成功的,后来又失败了。我不打算把30秒再改大,如果需要1分钟退一笔款,那还不全网吐槽,我还真没百度到这样的网页。感觉范围越来越小,只能瞄准IIS。于是我又做了一个测试网站,点击按钮发起一次无效退款,看是否超时。还真测试出来一些问题,重启应用程序池后会大概率出现超时,回收应用程序池后,也有一定几率造成超时;点击后在10秒内做10次无效退款,结果只有第一次失败,而且后面9次很快,基本在几百毫秒内完成。看来在没有缓存的情况下,这个双向证书的通信初始化确实要花很多时间。那么是不是由于这个初始化时间太长导致的网络超时呢?是不是要打印个日志出来看看?于是再改了下代码,加了时间消耗打印,不停重启应用程序池,果然有时候要超过10秒,最长的时候是17秒。不对啊,我不是改过超时时间是30秒么?拿那个改过的dll来试试,10秒之后就超时了。这是什么情况?

这就是我前面说到的问题。如果我们有一个第三方库,里面有个函数,例如

public int add(int i1,int i2=2)
{
    return i1 + i2;
}

调用的时候是这么写的,int i = add(1);编译好后测试,i = 3  但是如果我们只改第三方库函数的缺省值,改成i2=3,并且只编译第三方库后换回去,测试会得到 i=4 么?答案是不会。原因是编译 int i= add(1);的时候,虽然我们只写了一个参数,但是编译器会自动把另外一个参数自动加上去,用的数值是编译时第三方库函数参数的缺省值。所以后来即使改了第三方库的缺省值,但是调用方没有重新编译,那么还是用的之前的缺省值。

我以为自己把超时时间改到了30秒,其实啥也没干。赶紧再改改第三方库,直接在函数体内设置超时时间。换到测试网站里面,再怎么停止和回收应用程序池,都不会超时。

看来是简单问题复杂化了,另外还有一个疑问,为什么我之前采用的方式都能短时间治标,一会又over呢?原来IIS的应用程序池有一个设置,默认情况下只要20分钟没有人访问网页,就会自动将进程回收。我用的那些治标方式,其实都是失败一次后,刚好还有缓存没回收,于是看上去解决问题了。等到了晚上或者中午,没有业务发生时,进程被自动回收,自然又会出问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值