weixin_authorize
weixin_authorize copied to clipboard
获取access_token接口的每日实时调用量并没有变化的前提下,不定期出现了40001, access_token is invalid 错误
调用$client.download_media_url(media_id) 或者$weixin.send_template_msg()
: 不定期出现错误,但是微信的 每日实时调用量并没有变化,重复调用几次又正常了,一会又报错了。。。
{"code":40001,"en_msg":"invalid credential, access_token is invalid or not latest hint: [8KS0939ge11]","cn_msg":"获取access_token时AppSecret错误,或者access_token无效","result":{}}
正在修复。
- 调用的上下文代码方便贴出来看下么;
- token cache是基于哪种形式处理的,redis么?
- 报错频率高么?
- 应用的访问,并发大概有多少;
- “重复调用几次又正常了”,是如何重复调用的,代码贴下;
@yanchengv
@wikimo @lanrion
def send_template openid,template_id,data
url = $weixin.authorize_url(‘http://www.jinhuo.com’)
template_id = Settings.weixin.template1
response = $weixin.send_template_msg(openid, template_id, url, 'red', data)
end
- 报错频率挺高的
- 并发量不高,一共就500多个用户量
- 没有使用redis
- 后来我使用postman测试,重复调用接口,就会出现这种问题
这种问题出现是由于部署由mina
改为Capistrano
引起的,后来改回mina就正常了。找了一下原因,猜测应该是worker_processes
进程数量引起的。
- mina时 worker_processes 1 一切正常
- Capistrano时 worker_processes 4 就会出现上述问题
一直泪奔过来了,现在恢复正常也没敢在动环境测试,等缓一缓我测试一下是否这个原因
你是不是每台机器都new了一个 WeixinAuthorize::Client?这样子的话,会互相请求access_token的API,导致其他worker正在使用时失败。
请务必独立一个worker获取access_token,并让其他worker统一调用。
微信的官方wiki对此的解释:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183&token=&lang=zh_CN
1、为了保密appsecrect,第三方需要一个access_token获取和刷新的中控服务器。而其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则会造成access_token覆盖而影响业务;
weixin_authorize 使用自定义token的方法
https://github.com/lanrion/weixin_authorize/wiki/input-custom_access_token
即先在中控服务器使用weixin_authorize的 get_access_token接口获取,然后在其他业务服务器使用这些数据,参照wiki https://github.com/lanrion/weixin_authorize/wiki/input-custom_access_token
同时建议使用Redis。
这种基本就是重复调用引起的,建议源码也阅读下,以便于更好地使用gem @yanchengv
- cap -> worker -> 1 也观察下
- $weixin 看看这个东西是不是多个地方构建了;
- $weixin只有在项目的constant.rb文件调用了。
- 设置的是unicorn的workproess,只有一台服务器部署了一个项目。
- 如果重复调用,微信后台 每日实时调用量 确没有变化
workproess 如果是多个的话,可以看成是多个client获取access_token。
根据微信的建议,你需要独立获取access_token,然后供应给其他人使用。
项目里用了 MonitorMixin 的 synchronize 来避免 access_token 的竞争。 但只能避免线程间的竞争,如果用 Puma 开启了多个进程,是容易出现重复刷新 access_token 的问题。
可以通过第三方存储的锁机制。例如,用Redis的写入锁
Redis.set('lock_key', 'refreshing', ex: 3, nx: true)
https://github.com/Eric-Guo/wechat 这个项目中用了随机数检查过期时间的方式,但这种方式会有不稳定的结果。
@lingceng
获取access_token 最好是单独一台机器来维护.
添加分布式锁setnx 也是最好的方案.