本文主要讲CI2和CI3关于Session类库的区别。我们知道CI2的Session类使用了cookie来传递session数据。使用 cookie保存会话的好处在于可以节省服务器资源,但坏处也是显而易见的:不能存储太多数据,同时由于暴露了一些重要元数据(ip地址、user agent、session id、user data、上次活动时间),也不够安全(虽然可以加密和自动更新)。当然它也可以使用数据库来保存session数据,但配置有一定的复杂度。
CI3的Session的类库则完全重新,也不再把元数据信息以cookie的方式发送到客户端,它采用了原生的Session来保存会话数据。同时也不 再是简单地通过配置使用数据库来存储Session数据,而是通过drivers驱动的模式自由切换到不同的Session Driver。CI默认使用的driver为files,所以使用$this->load->library('session')加载 Session类时,自动使用files的驱动。
CI2和CI3的Session配置区别
在CI2中的application/config/config.php中的session配置如下:
02 |
$config [ 'encryption_key' ] = '_mahua_' ; |
04 |
$config [ 'sess_cookie_name' ] = 'ci_ssession' ; |
05 |
$config [ 'sess_expiration' ] = 7200; |
06 |
$config [ 'sess_expire_on_close' ] = TRUE; |
07 |
$config [ 'sess_encrypt_cookie' ] = FALSE; |
08 |
$config [ 'sess_use_database' ] = TRUE; |
09 |
$config [ 'sess_table_name' ] = 'ci_sessions' ; |
10 |
$config [ 'sess_match_ip' ] = FALSE; |
11 |
$config [ 'sess_match_useragent' ] = FALSE; |
12 |
$config [ 'sess_time_to_update' ] = 300; |
15 |
$config [ 'cookie_prefix' ] = "" ; |
16 |
$config [ 'cookie_domain' ] = "" ; |
17 |
$config [ 'cookie_path' ] = "/" ; |
18 |
$config [ 'cookie_secure' ] = FALSE; |
而在CI3中,配置就简单了很多:
1 |
$config [ 'sess_driver' ] = 'files' ; |
2 |
$config [ 'sess_cookie_name' ] = 'ci_session' ; |
3 |
$config [ 'sess_expiration' ] = 7200; |
4 |
$config [ 'sess_save_path' ] = NULL; |
5 |
$config [ 'sess_match_ip' ] = FALSE; |
6 |
$config [ 'sess_time_to_update' ] = 300; |
7 |
$config [ 'sess_regenerate_destroy' ] = FALSE; |
CI3中不再有$config['sess_match_useragent']配置,因为不再做此匹配。而配置$config['sess_expire_on_close'] 和$config['sess_encrypt_cookie'] 也不再存在:
07 |
$config [ 'sess_expire_on_close' ] = TRUE; |
10 |
$config [ 'sess_encrypt_cookie' ] = FALSE; |
13 |
$config [ 'sess_use_database' ] = TRUE; |
15 |
$config [ 'sess_table_name' ] = 'ci_sessions' ; |
18 |
$config [ 'sess_match_ip' ] = FALSE; |
20 |
$config [ 'sess_match_useragent' ] = FALSE; |
22 |
$config [ 'sess_time_to_update' ] = 300; |
27 |
$config [ 'sess_regenerate_destroy' ] = FALSE; |
配置驱动器
首先的改动CI3.0支持更多的方式去存储session,包括files, database, redis, memcached以及自定义,$config['sess_driver'] 来配置驱动器,默认的驱动器是files。
2 |
$config [ 'sess_driver' ] = ‘files’; |
5 |
$this ->load->library( 'session' , array ( 'driver' => 'files' , 'cookie_lifetime' =>300)); |
配置session save path
配置节sess_save_path会根据不同的驱动器,定义不同。
1.在files驱动器下,sess_save_path指的是session文件保存的路径。sess_save_path指定的文件夹目录需要是绝对路径,而且是可写的。
4 |
$config [ 'sess_save_path' ] = FCPATH. 'your/sess_save_path' ; |
2. 在database情形下,sess_save_path指代的是保存session的数据表名,如:
1 |
$config [ 'sess_driver' ] = 'database' ; |
2 |
$config [ 'sess_save_path' ] = 'ci_sessions' ; |
3.在redis情形下,需要安装phpredis 的php扩展。sess_save_path指代的是主机和端口地址,如:
1 |
$config [ 'sess_driver' ] = 'redis' ; |
4.在memcached情形下,也需要安装Memcached的php扩展,sess_save_path指代的也是主机和端口地址,如:
1 |
$config [ 'sess_driver' ] = 'memcached' ; |
2 |
$config [ 'sess_save_path' ] = 'localhost:11211' ; |
一个并发问题
随着web应用的发展,RIA越来越多,ajax请求会在客户端变得频繁。ajax请求是非阻塞的,这就意味着在同一时间会有两个持有相同Session
Id的请求达到服务器,并更改服务器上的Session 数据甚至重新产生新的session
id,这就会产生一个并发冲突。于是各种php的session
hanlder加入了锁机制,防止这种并发冲突。f当时用files驱动器时,锁机制是有效的,使用databse驱动器时,官方支持MySQL和
PostgreSQL数据库,因为它们有锁机制,其他数据库CI并不会支持。使用redis和Memcache
驱动器时,不具备锁机制,由CI模拟一种替代的锁。
在CI3以前的版本中,它的自动更新机制中,无论什么请求包括ajax,只要到达服务器就会更新session
id。到CI3时,已经加入了ajax请求的限制,如果是ajax请求,即使更新时间窗口到达,也不会更新session
id。这减少了并发冲突的可能性。但是锁机制的存在也会带来一些问题:
不加session_write_close(),同时运行三个进程,执行时间分别是10秒,20秒和30秒。而加入
session_write_close()后,则三个进程同时进行,只需要10秒。原因在于执行session_start()后
对应的session文件是被锁定的,直到当前脚本结束才会解锁。在锁定期间,另一个进程访问相同session id
要等文件解锁后session_start()才会开始。 在 session 设置好数据后调用 session_write_close()
将数据写入文件并且结束session可释放session文件资源供其他进程使用。CI官方手册提示到:在 session 设置好数据后调用 session_write_close()是个非常良好的习惯。
文件驱动器还是数据库驱动器?
相信有很多人在纠结使用文件驱动器,还是数据库驱动器。如果你认为使用database驱动器的效率要大于files驱动器的话,你只对了一半。官方的建
议是:如果网站的session不多,使用database驱动器效率要高,但是随着用户量的上升,files驱动器反而优势明显,超过
database。当然如果真要追求效率,官方则推荐使用tmpfs,如果你愿意的话,radis和memcache也是不错的选择。在某种情形下,自己擅长的技术就是最好的技术。
关于CI3 Session类库的文章到此结束了,如果有什么不懂的地方,可以提出来大家一起研究讨论。为此我单独开了一个文章,好积累一些在CI中文论坛中常常问到的问题,仅作参考。
http://www.ifixedbug.com/posts/how-to-use-codeigniter3-session-3