weixin_authorize icon indicating copy to clipboard operation
weixin_authorize copied to clipboard

获取access_token接口的每日实时调用量并没有变化的前提下,不定期出现了40001, access_token is invalid 错误

Open yanchengv opened this issue 8 years ago • 10 comments

调用$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":{}}

yanchengv avatar Jul 04 '16 05:07 yanchengv

正在修复。

lanrion avatar Jul 14 '16 12:07 lanrion

  • 调用的上下文代码方便贴出来看下么;
  • token cache是基于哪种形式处理的,redis么?
  • 报错频率高么?
  • 应用的访问,并发大概有多少;
  • “重复调用几次又正常了”,是如何重复调用的,代码贴下;

@yanchengv

wikimo avatar Jul 15 '16 05:07 wikimo

@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 就会出现上述问题

一直泪奔过来了,现在恢复正常也没敢在动环境测试,等缓一缓我测试一下是否这个原因

yanchengv avatar Jul 19 '16 01:07 yanchengv

你是不是每台机器都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

lanrion avatar Jul 19 '16 02:07 lanrion

同时建议使用Redis。

lanrion avatar Jul 19 '16 02:07 lanrion

这种基本就是重复调用引起的,建议源码也阅读下,以便于更好地使用gem @yanchengv

  • cap -> worker -> 1 也观察下
  • $weixin 看看这个东西是不是多个地方构建了;

wikimo avatar Jul 19 '16 05:07 wikimo

  • $weixin只有在项目的constant.rb文件调用了。
  • 设置的是unicorn的workproess,只有一台服务器部署了一个项目。
  • 如果重复调用,微信后台 每日实时调用量 确没有变化

yanchengv avatar Jul 19 '16 06:07 yanchengv

workproess 如果是多个的话,可以看成是多个client获取access_token。

根据微信的建议,你需要独立获取access_token,然后供应给其他人使用。

lanrion avatar Jul 19 '16 08:07 lanrion

项目里用了 MonitorMixin 的 synchronize 来避免 access_token 的竞争。 但只能避免线程间的竞争,如果用 Puma 开启了多个进程,是容易出现重复刷新 access_token 的问题。

可以通过第三方存储的锁机制。例如,用Redis的写入锁

Redis.set('lock_key', 'refreshing', ex: 3, nx: true)

https://github.com/Eric-Guo/wechat 这个项目中用了随机数检查过期时间的方式,但这种方式会有不稳定的结果。

lingceng avatar Sep 18 '19 07:09 lingceng

@lingceng
获取access_token 最好是单独一台机器来维护. 添加分布式锁setnx 也是最好的方案.

lanrion avatar Sep 18 '19 08:09 lanrion