资讯专栏INFORMATION COLUMN

Sessions共享技术设计

RdouTyping / 2109人阅读

摘要:方法销毁大于给定的所有数据,对本身拥有过期机制的系统如和而言,该方法可以留空。注意事项浏览器标签脚本执行过程中,打开标签访问同一个脚本,会被,直到执行完毕。

概述

分布式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数据,对本身拥有过期机制的系统如 MemcachedRedis 而言,该方法可以留空。

实现完成后使用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内部会清除对象, 所以有可能不调用writeclose回调函数, 这样可能会引发非预期的行为, 所以当使用对象作为会话保存管理器时, 需要通过注册 shutdown回调函数来规避风险。通常,你可以通过调用register_shutdown_function()函数来注册session_write_close()回调函数
d. 自定义session驱动

可通过memcachedredisdb等实现分布式session,考虑先实现redis session驱动


我们知道一般情况下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包

https://github.com/nrk/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://www.ucloud.cn/yun/29259.html

相关文章

  • session与登录机制

    摘要:每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。由于可以被人为的禁止,必须有其他机制以便在被禁止时仍然能够把传递回服务器。 github 地址:戳这里 session 概念 指一类用来在客户端与服务器之间保持状态的解决方案 这种解决方案的存储结构 特点 由于 Session 是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容。...

    nifhlheimr 评论0 收藏0
  • 都9102年了,还问Session和Cookie的区别

    摘要:前言最近看了一些同学的面经,发现无论什么技术岗位,还是会问到和的区别。所有学技术的同学都知道和函数怎么用,知道和的区别就是是储存在服务端的,是存储在浏览器的。的诞生是为了能让无状态的报文带上一些特殊的数据,让服务端能够辨识请求的身份。 1 前言 最近看了一些同学的面经,发现无论什么技术岗位,还是会问到 Session 和 Cookie 的区别。 所有学技术的同学都知道 Session ...

    Bowman_han 评论0 收藏0
  • Web Session 浅入浅出

    摘要:通过浏览器的,可以看到此次会话的请求内容和响应内容。是协议的一部分。真实的产品,一般是创建一个保证唯一的,不易猜测出来的字符串。因此需要数据持久化的多提供者的方案。 使用过几种Web App开发语言和框架,都会接触到Session的概念。即使是一个简单站点访问计数的功能,也常常使用Session来实现的。其他常用的领域还有购物车,登录用户等。但是,对Session一直是一知半解,知其然...

    李昌杰 评论0 收藏0
  • session和cookie机制及laravel框架下相关应用

    摘要:服务器检查该,以此来辨认用户状态。五下的相关应用应用在中配置如下配置项用于设置存储方式,默认是,即存储在文件中,该文件位于配置项配置的路径,即。配置项用于设置有效期,默认为分钟。配置项用于配置数据是否加密。 一、cookie的由来   当用户访问某网站时,web服务器会将部分信息保存到本地计算机上,当用户再次关顾该网站时,服务器会去查看用户是否登录过该网站,如果登录过,就会将这些记录在...

    NicolasHe 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<