[求助]多个 tomcat 并发读取 redis,有的会读取不到。

2019-01-11 05:26:09 +08:00
 MushiUta

今天晚上 APP 发版,其余功能都 OK,但是把 HTTP 更新到 HTTPS 之后,发现打开某个页面有 50%以上概率会收到服务器返回 token 失效的提示。然后一群人开始苦逼地排查问题。

首先查看该页面的网络请求。因为页面比较复杂,进入该页面的时候会同时发起 3 个请求,然后收到 token 失效提示的请求并不固定,所以怀疑是并发的问题。

照这个思路,试了下测试环境,并不能复现该问题(测试环境只有一台机器)。然后将生产环境关到只剩一台机器(本来有三台),也没再出现该问题。

将生产环境三台机器都打开,换回 HTTP,没有出现问题。

至此认为是,在有多台机器的情况下,使用 HTTPS,同时发起多个请求,会出现该问题。

查看服务器代码(其实之前也看了,没找到原因),收到 APP 请求后,会取 cookie 中的 sessionid,然后以 sessionid 为 key 去 redis 里面取保存的 token,再用来和 APP 上传的 token 比较。两者不相等的话,就认为是 APP 的 token 已经过期了。

感觉没有从 redis 里读取到 token,但是就几行代码,看来看去都觉得没啥问题。最后由于时间的关系,放弃这次上 HTTPS 的计划了。不过以后总是要上的,希望大佬给分析下,有可能是什么原因。

生产环境是三台 tomcat 服务器,共享一个 redis,通过某些策略做了负载均衡。HTTPS 使用的自签名证书,tomcat 将 80 端口的请求都重定向到了 443 端口。

我觉得大佬们可以完全当我们这边负责部署的人是小白,可能犯了某种搜索引擎都找不到的低级错误。毕竟 tomcat 配置 HTTPS 都配置了半天,而且鉴于上面的测试,我极度怀疑是这个配置出错导致的。

PS:可能上面我描述得不太准确(Android 程序员的视角),各位大佬将就着看吧,帮忙分析下原因,当然最好是有解决方案啦→_→等我睡醒再来感谢各位。

2324 次点击
所在节点    问与答
10 条回复
yuikns
2019-01-11 06:44:20 +08:00
https 用自签名这么神奇?就算嫌一年几百块钱的商用泛域名太贵,letsencrypt 有什么不对么?

tomcat 将 80 端口的请求都重定向到了 443 端口。 == 301 ?
"通过某些策略做了负载均衡" 感觉有坑....你可以再看看。
我觉得这可能不是 redis 的问题,是不是 sessionid 变了啊。
zgray
2019-01-11 07:14:42 +08:00
具体原因先不分析,你可以试试用 nginx 做 3 台服务器的负载均衡,然后把 SSL 加在 nginx 上,而不是 tomcat 上。然后 app 全部访问 tomcat。出问题的很大可能是会话的 session 的错误使用。如果可能,另一个建议是去掉 session,换用 token。
yidinghe
2019-01-11 08:20:53 +08:00
首先确定 sessionid 没问题,其次是保证 token 生成后一定要先存入 Redis 然后再返回给浏览器。有的 Redis 客户端是异步操作的,不要用异步操作。
HiJackXD
2019-01-11 08:27:51 +08:00
我也是菜鸡 还没用过 tomcat 的负载均衡 只知道负载均衡需要处理共享 session 的问题。用 http 没出现问题 可能当时恰好只访问了其中固定的一台。

我之前遇到过类似问题 不过是每次访问 sessionID 都变,最后查出来是 apache 反向代理 tomcat 后还需配置 session 绑定。

最简单也容易水平扩展的方法还是使用 token,服务器无状态化。
ebingtel
2019-01-11 08:43:11 +08:00
感觉是你们上了 https 之后,查询的 sessionid 和存储在 redis 中的 sessionid 不一致呀==
sayhi
2019-01-11 09:02:12 +08:00
tomcat 裸奔这么神奇,楼主的问题很可能出在 tomcat 配置 SSL 上面,建议 nginx 反向代理到 3 台 tomcat,在 nginx 中配置启用 SSL,证书不想付费的话 let's encrypt
cxh116
2019-01-11 09:02:36 +08:00
负载均衡是怎么实现的?
tomcat 有没有做 session 共享,还是通过负载均衡来做的会话保持?


看描述是在 tomcat 做的 https 配置?有没有可能之前的负载均衡是通过改写 cookie 来实现会话保持,然后现在上了 https 无法改写?
MushiUta
2019-01-11 13:04:15 +08:00
@yuikns #1
1.自签名证书这个我也木有办法,上级指示。
2.不太清楚他们负载均衡策略是啥,下午问问吧。
3.sessionid 应该是没有变的。

@zgray #2 @sayhi #6 确实感觉可以考虑用 nginx 反代试试。

@yidinghe #3 token 是早就存进去的,那几个接口并不会往 redis 写东西,redis 异步读取应该不会有问题吧。

@ebingtel #5 是一致的吧,redis 库里能查到。

@cxh116 #7 我不太懂这个,不过看起来是一个方向,下午去和后端人员说一下,让他们像这个方向看看。

@HiJackXD #4
1.HTTP 应该是三台都有访问到的,看日志有的。
2.sessionid 可能还是得用吧,不然他们后端改动好像有点大,而且现在没有定位到最终原因,也说服不了他们。
PS:大佬你是不是住回龙观某小区二楼~
HiJackXD
2019-01-11 19:07:28 +08:00
@MushiUta 你怎么知道的😳
MushiUta
2019-01-17 09:54:23 +08:00
@HiJackXD #9 我以前住那里 ORZ

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/525888

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX