Sessions共享技术设计
概述
分布式session是实现分布式部署的前提, 当前项目由于历史原因未实现分布式session, 但是由于在kubernets中部署多个pod时, 负载均衡的调用链太长, 导致会话不能保持, 所以迫切需要分布式session.
实现方案
a. 修改配置文件php.ini
直接在PHP中配置, 或者在代码中集成
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
b. 代码中动态设置
ini_set("session.save_handler", "redis");
ini_set("session.save_path", "tcp://127.0.0.1:6379");
c. 实现SessionHandlerInterface接口
php提供了SessionHandlerInterface接口, 按照此接口进行implements, 即可完成session共享。
/**
* @see http://php.net/manual/zh/class.sessionhandlerinterface.php
*/
SessionHandlerInterface {
abstract public bool close ( void )
abstract public bool destroy ( string $session_id )
abstract public int gc ( int $maxlifetime )
abstract public bool open ( string $save_path , string $session_name )
abstract public string read ( string $session_id )
abstract public bool write ( string $session_id , string $session_data )
}
/**
* @see http://php.net/manual/zh/class.sessionhandler.php
*/
MySessionHandler implements SessionHandlerInterface , SessionIdInterface {
public bool close ( void )
public string create_sid ( void )
public bool destroy ( string $session_id )
public int gc ( int $maxlifetime )
public bool open ( string $save_path , string $session_name )
public string read ( string $session_id )
public bool write ( string $session_id , string $session_data )
}
如上是PHP文档中对此interface的描述, 下面介绍下迅速过一下涉及到的几个方法:
| 方法 | 说明 | |
|---|---|---|
| open | 方法用于基于文件的session存储系统, 该方法中可不放置任何代码,可以将其置为空方法。 |
|
| close | 和open 方法一样,也可以被忽略,对大多数驱动而言都用不到该方法。 | |
| read | 应该返回与给定$sessionId, 相匹配的session数据的字符串版本。 |
|
| write | 应该讲给定$data 写到持久化存储系统相应的$sessionId destroy |
从持久化存储中移除 $sessionId 对应的数据。 |
| gc | 方法销毁大于给定 $lifetime 的所有session数据,对本身拥有过期机制的系统如 Memcached 和 Redis 而言,该方法可以留空。 |
实现完成后使用session_set_save_handler完成session驱动的注册
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
// 下面这行代码可以防止使用对象作为会话保存管理器时可能引发的非预期行为
register_shutdown_function('session_write_close');
session_start();
// 现在可以使用 $_SESSION 保存以及获取数据了
Warning: 在脚本执行完毕之后, PHP内部会清除对象, 所以有可能不调用
write和close回调函数, 这样可能会引发非预期的行为, 所以当使用对象作为会话保存管理器时, 需要通过注册shutdown回调函数来规避风险。通常,你可以通过调用register_shutdown_function()函数来注册session_write_close()回调函数
d. 自定义session驱动
可通过memcached、redis、db等实现分布式session,考虑先实现redis session驱动
<?php
//自定义interface
interface SessionInterface {
public function set($key, $value, $expire);
public function get($key);
public function del($key);
public function has($key);
public function all();
}
class RedisSession implements SessionInterface {
}
我们知道一般情况下cookie中存储着session id, 所以实现自定义session, 需要一些配置, 配置如下:
| 参数 | 默认值 | 选项 | 描述 |
|---|---|---|---|
| sess.driver | files | files/database/redis/memcached/custom | 使用的存储 session 的驱动 |
| sess.cookie_name | my_session | [A-Za-z_-] characters only | session cookie 的名称 |
| sess.expiration | 7200 (2 hours) | Time in seconds (integer) | 你希望 session 持续的秒数 如果你希望 session 不过期(直到浏览器关闭),将其设置为 0 |
| sess.save_path | NULL | None | 指定存储位置,取决于使用的存储 session 的驱动 |
| sess.time_to_update | 300 | Time in seconds (integer) | 该选项用于控制过多久将重新生成一个新 session ID 设置为 0 将禁用 session ID 的重新生成 |
| sess.regenerate_destroy | FALSE | TRUE/FALSE (boolean) | 当自动重新生成 session ID 时,是否销毁老的 session ID 对应的数据 如果设置为 FALSE ,数据之后将自动被垃圾回收器删除 |
使用时, $_SESSION 的操作改为 RedisSession 类操作.
例如:
$_SESSION['aa'] = 123; 改为 RedisSession::set('aa', 123);echo $_SESSION['aa']; 改为 echo RedisSession::get('aa');
redis驱动实现
Warning: 由于Redis没有锁机制, 这个驱动的锁是通过一个保持300s的值来模拟的。
Redis 是一种存储引擎,通常用于缓存,并由于他的高性能而流行起来,这可能也正是你使用 Redis 驱动的原因。
缺点是它并不像关系型数据库那样普遍,需要你的系统中安装了 phpredis 这个 PHP 扩展,它并不是 PHP 程序自带的。 可能的情况是,你使用 Redis 驱动的原因是你已经非常熟悉 Redis 了并且你使用它还有其他的目的。
当然不想安装phpredis客户端时, 能承受一定的性能损失, 可使用predis包
和文件驱动和数据库驱动一样,你必须通过 sess.save_path 参数来配置存储 session 的位置。 这里的格式有些不同,同时也要复杂一点,这在 phpredis 扩展的 README 文件中有很好的解释,链接如下:
https://github.com/phpredis/p...
Warning: 这里的 Session 类并没有真的用到 'redis' 的 session.save_handler , 只是 采用了它的路径的格式而已。
!
注意事项
a. 浏览器A标签脚本执行过程中,打开B标签访问同一个脚本,会被pending,直到A执行完毕。
原因该脚本执行了session_start(),而php session_start()后对该session的写入是排他的,只有当脚本执行结束或显式执行session_destroy()才能释放session文件锁。
b. 自定义session驱动并不是那么简单, 需要用到很多知识来正确的实现它。
你不仅要知道session一般的工作原理,而且要知道它在PHP中如何实现的,还要知道它的内部存储机制是如何工作的,如何去处理并发,如何去避免死锁(不能去掉锁),以及如何处理潜在的安全问题
原文地址:https://segmentfault.com/a/1190000016054843
Sessions共享技术设计的更多相关文章
- Spring boot集成Redis实现sessions共享时,sessions过期时间问题分析
Springboot鼓励零配置的方式,帮你做好大部分重复劳动的事,好到不能再好:具体的Redis安装方法和Springboot集成Redis方法,可以去搜索相关文章或参考该文章http://www.c ...
- Spring boot 、mybatis、swagger、c3p0、redis 和mongodb 整合
文件路径: 添加依赖: <?xml version="1.0" encoding="UTF-8"?> <project ...
- 【spark】SparkSession的API
SparkSession是一个比较重要的类,它的功能的实现,肯定包含比较多的函数,这里介绍下它包含哪些函数. builder函数public static SparkSession.Builder b ...
- 生产要不要开启MySQL查询缓存
一.前言 在当今的各种系统中,缓存是对系统性能优化的重要手段.MySQL Query Cache(MySQL查询缓存)在MySQL Server中是默认打开的,但是网上各种资料以及有经验的DBA都建议 ...
- centos 6.5 x64创建并挂载使用iscsi共享磁盘
前景摘要:NFS或iSCSI,哪个更好?文件 vs 块NFS使用文件级别的实施,服务器或存储阵列托管整个文件系统,客户到文件系统上读写文件,可以在阵列端对主存储数据进行重复数据删除.iSCSI和FC则 ...
- 基于nginx tomcat redis分布式web应用的session共享配置
一.前言 nginx 作为目前最流行的开源反向代理HTTP Server,用于实现资源缓存.web server负载均衡等功能,由于其轻量级.高性能.高可靠等特点在互联网项目中有着非常普遍的应用,相关 ...
- [Spring] spring-session + JedisPool 实现 session 共享
1.至少导入四个jar包: jedis spring-session spring-data-redis commons-pool2 2.bean配置 <?xml version="1 ...
- 跨应用Session共享
摘要:虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术.本文将详细讨论session的工作机制并且对在Java ...
- Asp.net mvc与PHP的Session共享的实现
最近在做的一个ASP.NET MVC的项目,要用到第三方的php系统,为了实现两个系统的互联互通.决定将两者的session打通共享.让asp.net mvc 和php 都能正常访问和修改Sessio ...
随机推荐
- 为什么使用 use strict
进入标志: "use script"; 使用方式: 可以在 js 代码的第一行,也可以使用在函数中.但是写在 js 代码第一行不利于文件合并,因此可以写在一个自调用函数的第一行 使 ...
- java四舍五入保留几位小数
double d = 3.1415926; String result = String.format("%.2f", d); // %.2f %. 表示 小数点前任意位数 2 表 ...
- JSP-Runoob:JSP XML 处理数据
ylbtech-JSP-Runoob:JSP XML 处理数据 1.返回顶部 1. JSP XML 数据处理 当通过HTTP发送XML数据时,就有必要使用JSP来处理传入和流出的XML文档了,比如RS ...
- E20170706-sl
erode vt. 侵蚀,腐蚀 vi. 逐渐毁坏; 削弱,损害; thin adj. 薄的; 瘦的; 细的; 稀少的; laptop n. 便携式电脑;
- [App Store Connect帮助]三、管理 App 和版本(2.5)输入 App 信息:本地化 App Store 信息
在添加 App 至您的帐户之后,您可以在“App 信息”页面添加语言并输入本地化元数据.若要查看受支持的语言列表,请参见 App Store 本地化.若要了解您可以本地化的属性,请参见必填项.可本地化 ...
- [Swift通天遁地]九、拔剑吧-(11)创建强大的Pinterest风格的瀑布流界面
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 汇编程序45:检测点13.2 (loop指令的中断例程)
安装程序: assume cs:code //loop指令的替代实现 code segment start: mov ax,cs mov ds,ax mov si,offset sub1 mov ax ...
- 【BZOJ2149】拆迁队(斜率优化DP+CDQ分治)
题目: 一个斜率优化+CDQ好题 BZOJ2149 分析: 先吐槽一下题意:保留房子反而要给赔偿金是什么鬼哦-- 第一问是一个经典问题.直接求原序列的最长上升子序列是错误的.比如\(\{1,2,2,3 ...
- Jenkins-SVN + Maven + Docker
第1步:安装插件 Subversion Plug-inMaven Integration pluginCloudBees Docker Build and Publish pluginDeploy t ...
- Elasticsearch之CURL命令的PUT和POST对比
PUT是幂等方法,而POST并不是. PUT用于更新操作,POST用于新增操作比较合适. PUT,DELETE操作是幂等的,所谓幂等就是指不管进行多少次操作,结果都一样. 比如,我用PUT修改一篇文章 ...