V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
MushiUta
V2EX  ›  问与答

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

  •  
  •   MushiUta · 2019-01-11 05:26:09 +08:00 via Android · 2531 次点击
    这是一个创建于 2177 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天晚上 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 程序员的视角),各位大佬将就着看吧,帮忙分析下原因,当然最好是有解决方案啦→_→等我睡醒再来感谢各位。

    第 1 条附言  ·  2019-01-11 13:09:20 +08:00

    找后端要来了一份HTTPS配置文件。

    <Connector executor="tomcatThreadPool"
        port="80" 
        connectionTimeout="20000"
        protocol="org.apache.coyote.http11.Http11Nio2Protocol"
        redirectPort="443"
        acceptCount="5000"
        maxPostSize="-1"
        acceptorThreadCount="16"
        maxHttpHeaderSize="102400"
        URIEncoding="utf-8"/>
    
    <Connector
        port="443" 
        protocol="org.apache.coyote.http11.Http11NioProtocol"
        maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
        clientAuth="false" sslProtocol="TLS"
        keystoreFile="xxx" 
        keystorePass="xxx"/>
    
    <Connector port="8009" protocol="AJP/1.3" redirectPort="443" />
    
    第 2 条附言  ·  2019-01-17 09:53:52 +08:00
    [结贴]
    最后发现是 HTTPS 的会话保持配置有问题,已解决。
    另外准备在下个版本抛弃 sessionId,只使用 token 鉴权。
    10 条回复    2019-01-17 09:54:23 +08:00
    yuikns
        1
    yuikns  
       2019-01-11 06:44:20 +08:00   ❤️ 1
    https 用自签名这么神奇?就算嫌一年几百块钱的商用泛域名太贵,letsencrypt 有什么不对么?

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

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

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


    看描述是在 tomcat 做的 https 配置?有没有可能之前的负载均衡是通过改写 cookie 来实现会话保持,然后现在上了 https 无法改写?
    MushiUta
        8
    MushiUta  
    OP
       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
        9
    HiJackXD  
       2019-01-11 19:07:28 +08:00 via iPhone
    @MushiUta 你怎么知道的😳
    MushiUta
        10
    MushiUta  
    OP
       2019-01-17 09:54:23 +08:00
    @HiJackXD #9 我以前住那里 ORZ
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2842 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:28 · PVG 19:28 · LAX 03:28 · JFK 06:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.