最近项目组搞冲刺,忙到爆,五月一篇文章也没写,眼看六月又将结束,抓住一个周末抽点时间写写最近工作中遇到的几个小问题,希望能给遇到相同问题的同学些许帮助。
(冲刺阶段的装备-红头巾)
问题1:用户进入微信公众号菜单时偶现oAuth2.0授权失败
问题背景:
我们有些功能以微信公众号的形式提供出去,为了避免用户使用时频繁输入用户名密码,所以借助微信的oAuth2.0鉴权流程实现了免登录的效果,但是有个前提是需要用户提前做一步绑定操作,将我们体系的userid和微信体系中的openid做一个绑定,只要有了openid就可以关联到用户。
下面看下微信oAuth2.0的接入流程。
就在上图中4.1调用开放api获取access_token时会偶现
{"errcode":40163,"errmsg":"code been used”}
排查过程:
什么情况下会对同一个auth _code发起重复调用呢?
- 是httpclient(4.1由httpclient发起,所以先怀疑它)的重试吗?不是,我看了上一次调用的日志,没有异常而且响应很快,完全不具备httpclient重试的条件。
- 是业务代码的重试吗?看了代码并没有任何重试的痕迹。
- 有没有可能是第4步“带着auth_code,访问第三方应用指定的地址”重复请求了呢?带着这种疑问开始找证据,果不其然,从nginx的access log中很快发现了蛛丝马迹。
grep auth_code access.log
第一次请求
第二次请求
可以看到两次使用的code是同一个,还有个细节是第一次请求的http状态码是499,看下网络上对nginx 499状态码的解释:
499,客户端关闭连接,这个状态码并不是http协议中定义的status code,而是nginx自己定义的一个状态码。由于服务器处理请求较多,客户端在有效时间内没有得到答复,主动关闭了连接。
到这儿我大胆的猜测这是微信客户端加的一种优化策略,如果某个请求超时,那就断开重试一次,从上面两次请求的access log可以得出微信认定的超时时间为20s,正是这种优化才造成了这个问题,怎么优化呢?
解决方式:
也许有人说这属于微信的bug啊,作为一个第三方应用提供方我们怎么优化呢,其实不然,某种角度来说是我们没有做好“幂等“才导致这种问题发生,微信客户端在此时只是一个普通的浏览器而已,即使它没有这种“重试”,谁又能保证后面的环节没有重试发生呢,比如nginx,所以废话不多说还是把“幂等”做起来,解决方式很简单,引入redis对auth_code的查询结果暂存几分钟,如果报“code been used”那就从redis获取一次。
问题2:站点升级https以后导致附件预览功能失败
问题背景:
笔者所在的团队目前负责B端的业务,涉及到附件预览,其中附件预览是独立的服务,当业务中有附件预览需求时会重定向到预览服务进行在线预览。
大体流程如下:
1.用户在业务方站点发起预览请求;
2.业务方拼接相关参数重定向到预览服务;
3.预览服务通过业务方传递的附件链接调用业务方接口下载附件到本地;
4.预览服务将下载的附件转换成html、图片、pdf等供用户在线预览。
之前一直运行的好好的,但是业务站点由http升级到https以后有部分用户反映,附件预览失败,报错截图如下:
第一反应我是有点懵的,预览服务本身就是个http地址,怎么还牵扯到证书了,紧接着我让客户把浏览器地址栏内容复制给我,果然是个https地址,赶快找运营借来测试账号尝试复现,结果在我浏览器上没复现出来,在其他同事浏览器上复现了,都是chrome只是版本不一样,到这里还是云里雾里的,不知道发生了什么,猜测可能是浏览器做了某些处理导致。
解决方式:
紧急将预览服务也增加了https支持,问题随之解决,至于原因我一直没有找到特别确切的答案,所以在此也就不多说了,猜测是一个叫做HSTS的东西作祟,当你发现http被强制重定向为https的时候希望你可以联想到它,有兴趣的可以看下知乎上ThoughtWorks团队写的一篇文章https://zhuanlan.zhihu.com/p/25537440。
问题3:git分支乱合并
最近团队出现过好几次git分支合并错的问题,比较致命的是把开发分支合并到某个release分支上,更夸张的是居然运行了一个晚上,还好第二天一大早就有测试发现了问题,紧急回退才避免了事故扩大。
下图是我们团队的git flow流程,和标准的git flow差别不小,目前我们有固定的迭代周期和发版计划,所以整体流程和TrunkBased很相似,直接在master开发,到达发版节点以后发布master代码,发布完成以后拉取release分支,用来做历史版本bug的修复。
某天晚上有个小哥修改bug,本意可能是改完了把release合回master,但是手抖居然合反了,导致线上运行着未经测试的代码,想想我都一头汗,事后他过来找我。
“哥,帮我回退下代码,昨天把代码合错了”
“嗯”(我咬着后槽牙回答到)
问题虽然解决了,同时也映射出我们的代码合并流程其实是存在问题的,试图通过一种口口相传的方式显然是不行的,得想办法借助工具来解决,通过调研我大概发现有以下两种办法:
1.在git服务端设置保护分支,只允许某几个人的合并,甚至只能通过MR的方式来合并分支,将风险性行为交给团队内“德高望重“的人来实施;
2.在git客户端通过git hook的方式来实施,检测到某些风险合并时拒绝merge。
最终我使用客户端hook的方式规避这种风险,主要原因是想让开发者提前意识到这种问题,不要把风险往后传递。
实践方式如下:
1. 在.githooks目录下实现commit-msg这个hook,git已经内置了这个文件只是增加了sample后缀,删除sample就会启用这个hook;
2. 编写检测脚本,这段引用自互联网,侵删。
https://www.cnblogs.com/SteelArm/p/12773485.html
#!/bin/sh BLACKLIST=("master" "origin/master") forbid_list=() if [[ -e .git/MERGE_HEAD ]]; then heads=`ls .git/refs/heads` for bl in "${BLACKLIST[@]}"; do if [[ -n `echo ${heads} | grep -oP "(^| )${bl} "` ]]; then forbid_list+=(`cat .git/refs/heads/${bl}`) fi done merge_head=`cat .git/MERGE_HEAD` for br in "${forbid_list[@]}"; do if [[ ${merge_head} == ${br} ]]; then echo -e " 33[41;37m 合并了黑名单中的分支 33[0m " echo -e " 33[41;37m 请使用 git merge --abort 命令终止合并 33[0m" exit 1 fi done fi
3. 最终效果,如果错误合并了会报错提示;
写在最后
以上是我近期工作中遇到的几个比较有意思的问题,在这里分享出来,希望下一次你遇到同样问题的时候能带来些许帮助。