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

2018-12-24 11:59:17 +08:00
 s609926202

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

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

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

2483 次点击
所在节点    问与答
21 条回复
woodensail
2018-12-24 12:18:36 +08:00
没做分布式 session,跳转到第二台服务器后 session 丢失不是正常现象吗?
s609926202
2018-12-24 13:50:56 +08:00
@woodensail 但是用了 coodie 保存登录信息的,没升级到 7.2 之前,是可以保持会话状态的
woodensail
2018-12-24 13:53:56 +08:00
@s609926202 很迷啊,如果你没做什么。php 不会自动支持分布式 session 的。
zakokun
2018-12-24 13:55:25 +08:00
是不是你们配置改了 原来用的是 redis 保存的 session 升级 php 以后 php 用本地文件保存的 session 自然不能跨机器了
s609926202
2018-12-24 14:10:56 +08:00
@zakokun 你的意思是即使使用本地 cookie 保存用户登录信息,但是对负载均衡来说,也必须做一些关于分布式 session 的工作的?
zakokun
2018-12-24 14:15:23 +08:00
如果你们没做 jwt 的话 登录是靠浏览器的 cookie + 服务器的 session 一起来判断登录状态的,所以负载均衡一定是靠单独的机器保存 session 的,比如 单独的一台 redis 机器 你看看现在 php 读取的 php.ini 文件是哪个把,和原来的是不是一致
mansurx
2018-12-24 14:26:39 +08:00
cookie 是客户端本地的。服务端 session 不能各自处理各自的,应该统一放到 redis 吧
also24
2018-12-24 14:36:43 +08:00
这就体现出了很多人混淆 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
2018-12-24 14:36:50 +08:00
OK,背景普及完毕,楼主的问题是怎么出现的呢?
很简单,session-id 是 A 服务器生成的,你去 B 服务器查,当然查不到相应的 session-data 啦。

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

(治本) 2、让 B 服务器能从 A 服务器拿到 session-data,这就是其它 V 友说到的 session 同步。
s609926202
2018-12-24 14:49:50 +08:00
@also24
刚咨询了一些,AWS ELB 不支持 ip_hash,但支持粘性会话、和这个应该功能一致
xenme
2018-12-24 14:52:38 +08:00
ELB 调整下 persist 设置就好了。
s609926202
2018-12-24 14:56:51 +08:00
@xenme
你说的是 persistence ? sticky sessions?
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
2018-12-24 15:10:28 +08:00
@s609926202 是的。再 ELB 层面进行。
xiaoxinshiwo
2018-12-24 15:45:29 +08:00
看看 cookie 的 path 是否跟老的一样
lhx2008
2018-12-24 15:56:09 +08:00
@also24 如果基于 hash 或者粘性会话,那负载每一台都不能挂,新加机器也很难合理拉到客,感觉这个缺点挺伤的
also24
2018-12-24 16:05:13 +08:00
@lhx2008 #16
但是如果用共享 session 的方式,session 方面的压力其实也还是压在了一个单点。

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


@also24 #8
勘误一下:“另外就是 flask 只对 session 做了签名,没做校验”
应修改为:“另外就是 flask 只对 session 做了签名校验,没做加密”
reself
2018-12-24 19:10:24 +08:00
@also24 和签名相比,用加密的话性能损耗太大了。用签名就是不能用来存机密信息。

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

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

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

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

© 2021 V2EX