解决Nginx负载均衡的Session共享问题
目前来说,蜂窝的产品基本上都是基于微信公众平台进行开发。为了可以快速开发,我使用了PHP的CodeIgniter框架配合EasyWeChat。
CodeIgniter和EasyWeChat 是什么?
CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而“优雅”的工具包,它可以为开发者们建立功能完善的 Web 应用程序。
传送门:CodeIgniter
EasyWeChat 是一个开源的微信非官方 SDK。
传送门:EasyWeChat
而微信公众平台的开发,最基础的一个模块就是通过OAuth模块获取用户信息进而实现相关的业务逻辑。
什么是OAuth?
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。
OAuth的授权流程
OAuth的授权流程步骤解释:
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
摘自:RFC 6749
而通过以上的授权流程之后,都会用Session 来保持会话,维持用户的状态并跟踪他们的行为。但是在这里就遇到了一个问题:“在微信内置浏览器跳转的时候Session丢失”。
一个bug我改了两天
1. 从框架入手
我的第一反应肯定就是CodeIgniter的框架问题,因为CodeIgniter的Session类并不使用PHP本身的session,而是使用自己的Session类。
CodeIgniter的Sessions 是怎样工作的?
当页面载入后,Session类就会检查用户的cookie中是否存在有效的session数据。如果session数据不存在(或者已经过期),那么就会创建一个新的session并把他保存在cookie中。如果session数据存在,那么他的信息就会被更新,同时cookie也会被同时更新。每次更新都会重新生成session_id的值。
根据文档的提示去检查了下Cookie,发现并不是所有的页面的自定义 session 数据都会丢失。也就是说在页面跳转的过程中保存在cookie中的session数据在某些页面会丢失,并且不是在固定的某个页面丢失!
烦躁2. Session过期?
在修改了Session 相关的参数后,这个假设很快就被排除。
3. 使用xdebug跟踪全部业务逻辑
在排除了框架以及一些简单配置可能造成的影响之后,我开始使用xdebug跟踪全部业务逻辑,期待能找到session的丢失规律。
其实到这里,本应该就找到了问题。但是由于自己的大意,我并没有注意到某些细节的变化,完全陷入了参数对不对以及在哪丢失的细节中去,反复思考到底为什么?
之后在google的过程中,Segmentfault上的一个问答给了我一些思路:
传送门:PHP 实现多台服务器共用SESSION方案?
看了这篇文章之后,突然恍然大悟。也就联想到了之前在朗玛(我之前工作的一个公司)的培训。在朗玛工作的时候,最基本的处理都会把session存在memcache中。
恍然大悟
蜂窝目前的系统架构由于使用了nginx做负载均衡,这样同样一个页面会被分配到不同的服务器上,此时如果session不同步的话,就会出现问题。
由于目前蜂窝的产品并没有这么大的访问请求,所以就还没有到利用缓存技术改善系统性能的阶段。基于此,我使用了CodeIgniter框架自带的解决方案:“将 Session 数据存入数据库。”
哎,真的被自己蠢哭了!