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

负载均衡中,登录使用 Cookie,但是还是不能维持会话状态,可能会是神马原因?

  •  
  •   s609926202 · 2018-12-24 11:59:17 +08:00 · 2499 次点击
    这是一个创建于 2188 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Wordpress,登录默认就是 Cookie。服务器是 AWS 的 2 台 EC2,前面又配置了 AWS,昨天升级了 PHP 到 7.2 后,登录状态就不能维持了。

    1:分别对两台服务器 stop,会话登录完全没问题;都 start 后,就会在登录后,如果跳转到第二台服务器,会话显示失效 2:其他原因?

    有经验的大佬知道这个是啥原因吗?

    第 1 条附言  ·  2018-12-24 14:50:24 +08:00
    ... 前面又配置了 AWS ...

    这句话写错了,是:前面又配置了 ELB (弹性负载均衡)
    21 条回复    2018-12-25 08:51:42 +08:00
    woodensail
        1
    woodensail  
       2018-12-24 12:18:36 +08:00
    没做分布式 session,跳转到第二台服务器后 session 丢失不是正常现象吗?
    s609926202
        2
    s609926202  
    OP
       2018-12-24 13:50:56 +08:00
    @woodensail 但是用了 coodie 保存登录信息的,没升级到 7.2 之前,是可以保持会话状态的
    woodensail
        3
    woodensail  
       2018-12-24 13:53:56 +08:00
    @s609926202 很迷啊,如果你没做什么。php 不会自动支持分布式 session 的。
    zakokun
        4
    zakokun  
       2018-12-24 13:55:25 +08:00   ❤️ 1
    是不是你们配置改了 原来用的是 redis 保存的 session 升级 php 以后 php 用本地文件保存的 session 自然不能跨机器了
    s609926202
        5
    s609926202  
    OP
       2018-12-24 14:10:56 +08:00
    @zakokun 你的意思是即使使用本地 cookie 保存用户登录信息,但是对负载均衡来说,也必须做一些关于分布式 session 的工作的?
    zakokun
        6
    zakokun  
       2018-12-24 14:15:23 +08:00
    如果你们没做 jwt 的话 登录是靠浏览器的 cookie + 服务器的 session 一起来判断登录状态的,所以负载均衡一定是靠单独的机器保存 session 的,比如 单独的一台 redis 机器 你看看现在 php 读取的 php.ini 文件是哪个把,和原来的是不是一致
    mansurx
        7
    mansurx  
       2018-12-24 14:26:39 +08:00 via Android
    cookie 是客户端本地的。服务端 session 不能各自处理各自的,应该统一放到 redis 吧
    also24
        8
    also24  
       2018-12-24 14:36:43 +08:00   ❤️ 3
    这就体现出了很多人混淆 session / session-data / session-id / cookies 的情况了。


    不少人因为 cookies 里存储了一个叫做 session 的变量,就粗暴的认为这是 session 的本体了。

    我倾向于把东西划分为 session 和 session-data 来解释:
    session 是个虚拟概念,代表了一个虚拟的会话过程
    session-data 是个实体概念,代表这个会话中的独享数据(例如登录状态、用户信息等)

    在大部分实现中( flask 除外),cookies 里存储的只是 session-id,只是一个索引 id 而已,就一串字符 id 而已。
    真正的 session-data,其实是存储在服务端程序中的,服务端程序,根据 session-id,取出了 session-data 参与运算渲染。
    于是在外界看来,就好像这个 session 是通过 cookies 里的 session-id 来维持的一样。




    这就造成了许多人 “ session 是存储在 cookies 中” 的误解。
    同时也造成了,在讨论 session 的时候,很多人混淆 session 会话 / session-data / session-id 的情况。


    当然,刚才被我排除掉的 flask,人家是真的把 session-data 存储在 cookies 中的(即 “客户端 session ”),所以在使用 flask 的时候,要处理好 secret_key 的安全性,否则容易出现 伪造 session 的问题,另外就是 flask 只对 session 做了签名,没做校验,所以本地 session 是可以被解码查看的。当然那就是另一个话题了,不多说。
    also24
        9
    also24  
       2018-12-24 14:36:50 +08:00   ❤️ 2
    OK,背景普及完毕,楼主的问题是怎么出现的呢?
    很简单,session-id 是 A 服务器生成的,你去 B 服务器查,当然查不到相应的 session-data 啦。

    那么问题怎么解决呢?简单提两个方法:
    (推荐) 1、让从 A 服务器拿 session-id 的用户,永远只访问 A 服务器,可以通过负载均衡服务器的配置实现(例如 nginx 的 ip_hash )

    (治本) 2、让 B 服务器能从 A 服务器拿到 session-data,这就是其它 V 友说到的 session 同步。
    s609926202
        10
    s609926202  
    OP
       2018-12-24 14:49:50 +08:00
    @also24
    刚咨询了一些,AWS ELB 不支持 ip_hash,但支持粘性会话、和这个应该功能一致
    xenme
        11
    xenme  
       2018-12-24 14:52:38 +08:00
    ELB 调整下 persist 设置就好了。
    s609926202
        12
    s609926202  
    OP
       2018-12-24 14:56:51 +08:00
    @xenme
    你说的是 persistence ? sticky sessions?
    also24
        13
    also24  
       2018-12-24 15:09:46 +08:00
    @s609926202 #10
    看了下 ELB 关于粘性会话的描述,是没问题的,而且是基于 cookies 实现的,比基于 ip 识别的 ip_hash 方案效果会更好。

    https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/classic/elb-sticky-sessions.html
    xenme
        14
    xenme  
       2018-12-24 15:10:28 +08:00
    @s609926202 是的。再 ELB 层面进行。
    xiaoxinshiwo
        15
    xiaoxinshiwo  
       2018-12-24 15:45:29 +08:00
    看看 cookie 的 path 是否跟老的一样
    lhx2008
        16
    lhx2008  
       2018-12-24 15:56:09 +08:00 via Android
    @also24 如果基于 hash 或者粘性会话,那负载每一台都不能挂,新加机器也很难合理拉到客,感觉这个缺点挺伤的
    also24
        17
    also24  
       2018-12-24 16:05:13 +08:00
    @lhx2008 #16
    但是如果用共享 session 的方式,session 方面的压力其实也还是压在了一个单点。

    另外在 AWS 的 ELB 文档中有关于单点失效情况下的策略的描述:
    如果实例失败或者实例运行状况不佳,负载均衡器会停止将请求路由到该实例,并根据现有负载均衡算法来选择新的运行状况良好的实例。此时会将请求路由到新实例,就像没有 Cookie 一样,会话不再具有粘性。
    lhx2008
        18
    lhx2008  
       2018-12-24 16:10:33 +08:00 via Android
    @also24 seesion-data 可以存 redis 集群哈哈,不过可能有点过度设计了
    also24
        19
    also24  
       2018-12-24 16:42:26 +08:00
    @lhx2008 #18
    哈哈哈哈,所以我还是推荐直接在负载均衡端解决,业务性能损耗小,实现简单。
    追求完美实现的话,实在是太折腾了~


    @also24 #8
    勘误一下:“另外就是 flask 只对 session 做了签名,没做校验”
    应修改为:“另外就是 flask 只对 session 做了签名校验,没做加密”
    reself
        20
    reself  
       2018-12-24 19:10:24 +08:00 via Android
    @also24 和签名相比,用加密的话性能损耗太大了。用签名就是不能用来存机密信息。
    godgrp
        21
    godgrp  
       2018-12-25 08:51:42 +08:00 via iPhone
    php 配置下,session 存 redis,就一行配置,当然前提是要有 redis,memcached 也可以
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2347 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 15:52 · PVG 23:52 · LAX 07:52 · JFK 10:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.