background image

一、问题起源
稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用
不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整
个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,
只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但
还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,
仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个

 

服务器之间如何实现共享 SESSION 数据的问题。
二、PHP SESSION 的工作原理

 

在解决问题之前,先来了解一下 PHP SESSION 的工作原理。在客户端(如浏览器)登录

 

网站时,被访问的 PHP 

 

页面可以使用 session_start() 

 

打开 SESSION,这样就会产生客户

 

端的唯一标识 SESSION ID

 

(此 ID 

 

可通过函数 session_id() 获取/设置)。SESSION ID 可

以通过两种方式保留在客户端,使得请求不同的页面时, PHP 程序可以获知客户端的 
SESSION ID

 

;一种是将 SESSION ID 

 

自动加入到 GET   

的 URL 

 

中,或者 POST 的表单中,

 

默认情况下,变量名为 PHPSESSID

 

;另一种是通过 COOKIE

 

,将 SESSION ID 保存在 

COOKIE  

 

中,默认情况下,这个 COOKIE 

 

的名字为 PHPSESSID。这里我们主要以 

COOKIE 方式进行说明,因为应用比较广泛。

 

那么 SESSION 的数据保存在哪里呢?当然是在服务器端,但不是保存在内存中,而是保
存 在 文 件 或 数 据 库 中 。 默 认 情 况 下 , php.ini  

 

中 设 置 的 SESSION   保 存 方 式 是 

files(session.save_handler = files

 

),即使用读写文件的方式保存 SESSION 数据,而 

SESSION  

 

文 件 保 存 的 目 录 由 session.save_path 

 

指 定 , 文 件 名 以 sess_   为 前 缀 , 后 跟 

SESSION ID,如:sess_c72665af28a8b14c0fe11afe3b59b51b。文件中的数据即是序列化之后

 

的 SESSION 

 

数据了。如果访问量大,可能产生的 SESSION 文件会比较多,这时可以设置

 

分 级 目 录 进 行 SESSION   文 件 的 保 存 , 效 率 会 提 高 很 多 , 设 置 方 法 为 :
session.save_path="N;/save_path" , N   为 分 级 的 级 数 , save_path   为 开 始 目 录 。 当 写 入

 

SESSION 数据的时候,PHP 

 

会获取到客户端的 SESSION_ID

 

,然后根据这个 SESSION ID 

 

到指定的 SESSION 

 

文件保存目录中找到相应的 SESSION 文件,不存在则创建之,最后

 

将数据序列化之后写入文件。读取 SESSION 数据是也是类似的操作流程,对读出来的数

 

据需要进行解序列化,生成相应的 SESSION 变量。

 

三、多服务器共享 SESSION 的主要障碍及解决办法

 

通过了解 SESSION 的工作原理,我们可以发现,在默认情况下,各个服务器会各自分别

 

对 同 一 个 客 户 端 产 生 SESSION ID , 如 对 于 同 一 个 用 户 浏 览 器 , A  服 务 器 产 生 的 
SESSION   ID  

 

是 30de1e9de3192ba6ce2992d27a1b6a0a

 

, 而 B   服 务 器 生 成 的 则 是 

c72665af28a8b14c0fe11afe3b59b51b。另外,PHP 

 

的 SESSION 数据都是分别保存在本服务

器的文件系统中。如下图所示:
 

 

确定了问题所在之后,就可以着手进行解决了。想要共享 SESSION 数据,那就

 

必须实现两个目标:一个是各个服务器对同一个客户端产生的 SESSION ID 必

 

须相同,并且可通过同一个 COOKIE 进行传递,也就是说各个服务器必须可以读取同一

 

个名为 PHPSESSID   

的 COOKIE

 

;另一个是 SESSION 数据的存储方式/位置必须保证各个

服务器都能够访问到。

 

简单地说就是多服务器共享客户端的 SESSION ID,同时还必须共

 

享服务器端的 SESSION 数据。

 

第一个目标的实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,