目录
参考
概要
共享Session
测试
服务器及负载均衡如何实现Session共享
问题:
由于生产环境需要高可用,所以增加了两台服务器做高可用集群,然后搭建完成之后,出现了一些登录态失效需要重新登录的问题。
原因:
定位问题发现是因为用户登录态是保存在Session中的,默认是保存在文件中的,且没有做共享Session,导致在某一台登录成功之后,写入到Session文件中,然后刷新页面就有可能请求到另一台服务器上,而另一台服务器中的Session文件是没有该登录态的,就会导致服务器认为用户没有登录需要重新登录
解决方法:
一般业界通用的做法有两种:
Session保持(会话保持)是我们见到最多的名词之一,通过会话保持,负载均衡进行请求分发的时候保证每个客户端固定的访问到后端的同一台应用服务器。会话保持方案在所有的负载均衡都有对应的实现。而且这是在负载均衡这一层就可以解决Session问题。
会话保持看似解决了Session同步的问题,但是却带来的一些其它方面的问题:
所以一般呢,更加推荐使用 Redis/Memcache等Nosql来做会话共享(Session共享)
这里只讲使用 Memcache来做Session共享
Memcache服务端和客户端(PHP)的安装见:【Memcache】Linux和Windows下Memcache服务端和客户端(PHP)的安装【原创】
对于PHP来说,实现Session共享,其实就是把Session的存储,从默认的文件存储改成使用Memcache来存储即可,有三种方法:
1. 修改php.ini
修改php.ini就是全局设置,修改后所有的Session默认使用Memcache,如果有多个memcached服务端的话,用逗号,隔开
# memcache扩展,如果有多个memcached服务端的话,用逗号,隔开
session.save_handler = memcache
session.save_path = "tcp://127.0.0.1:11211"
# memcached扩展,如果有多个memcached服务端的话,用逗号,隔开
session.save_handler = memcached
session.save_path = "127.0.0.1:11211"
修改后,重启php-fpm和nginx,然后可以通过查看phpinfo页面的session查看是否生效
如图:
注意:如果是memcached的话,那么图片里面就会是memcached了
注意:如果修改后发现phpinfo页面还是指向默认的文件缓存地址/tmp,说明还有其他的Session配置,在Linux中php-fpm的配置文件:/etc/php-fpm.conf或者/etc/php-fpm.d/*.conf中,而且它们的优先级比php.ini高,会覆盖php.ini中的配置,所以也需要在这里面修改:
# memcache扩展,如果有多个memcached服务端的话,用逗号,隔开
php_value[session.save_handler] = memcache
php_value[session.save_path] = "tcp://127.0.0.1:11211"
# memcached扩展,如果有多个memcached服务端的话,用逗号,隔开
php_value[session.save_handler] = memcached
php_value[session.save_path] = "127.0.0.1:11211"
然后重启php-fpm和nginx即可
2. 设置.htaccess
在某个目录下,修改.htaccess:
# memcache扩展,如果有多个memcached服务端的话,用逗号,隔开
php_value session.save_handler "memcache"
php_value session.save_path "tcp://127.0.0.1:11211"
# memcached扩展,如果有多个memcached服务端的话,用逗号,隔开
php_value session.save_handler "memcached"
php_value session.save_path "127.0.0.1:11211"
这个方法一般不推荐
3. 代码
PHP代码中顶部加上:
这个是只影响到该文件,一般也不会这么用
写一个PHP文件:
注意:以下测试的代码是针对Memcache扩展的,如果是Memcached扩展的话,实例化类的时候需要使用$mem = new Memcached;
addServer('127.0.0.1', 11211)){
var_dump('连接失败!');
}
var_dump($mem->get($session_id));
然后在浏览器访问,然后再注释掉$_SESSION['test_ddd'] = 'Hello World';,再去访问,看看能不能访问到即可
也可以使用telnet来查看memcached中是否有数据:
[root@www html]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get memc.sess.key.df07ae825edf170a4d2d1b417ddf445d
VALUE memc.sess.key.df07ae825edf170a4d2d1b417ddf445d 0 28
test_ddd|s:11:"Hello World";
END
注意:get memc.sess.key.df07ae825edf170a4d2d1b417ddf445d,前面的memc.sess.key是Memcached默认的前缀,后面跟着的是session_id的值
注意:session的前缀,可以通过phpinfo页面查看: