12
回答
php中的session性能很烂吗?
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   
很多php程序使用cookie代替session
PHP
举报
共有12个答案 最后回答: 3年前
默认情况下开启PHP会话,会在服务器端创建一个sess_PHPSESSID文件,返回一个名为PHPSESSID的cookie给浏览器.PHP操作$_SESSION数组添加和访问会话数据.

PHP同一个会话之间共享同一个对象实例:
object通过serialize序列化成string,然后保存到会话变量中:
$_SESSION['object'] = serialize($object);
在使用这个会话(PHPSESSID)发出的其他http请求通过反序列化获取对象:
$object = unserialize($_SESSION['object']);
当然,数组也一样可以这样存储到一个会话变量中,非常方便有木有.

PHP会话存储默认使用files,对应php.ini配置项session.save_handler=files
存储位置默认是/tmp,对应session.save_path=/tmp

如果你觉得用文件系统保存会话文件会造成磁盘I/O过大,你完全可以用Memcache/Redis来存储会话.
PECL扩展memcache和redis都提供了session处理器,用于存储PHP会话内容.
http://pecl.php.net/package/memcache
http://php.net/manual/zh/memcache.ini.php
http://pecl.php.net/package/redis
https://github.com/nicolasff/phpredis/

Ubuntu可以这样安装:
sudo apt-get install memcached redis-server
sudo apt-get install php5-memcache php5-redis
pear install pecl/memcache

配置php.ini,加入:
extension=memcache.so
extension=redis.so
再把
session.save_handler = files
session.save_path = "/tmp"
改为(memcache):
session.save_handler = memcache
session.save_path = "tcp://127.0.0.1:11211"
改为(redis):
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

session.save_path中多台memcache/redis服务器可以用逗号隔开.
session.save_path里的URL还可以可以包含一些参数,比如memcache的persistent,weight,timeout,retry_interval.

不能说PHP的session性能很烂,而是说计算机的io效率不高!

PHP默认session是以文件形式保存在本地文件系统中,每次访问都是做io操作,并发大的时候,必然会导致session文件爆发,导致读取文件变慢。

换一种方式,将session保存到内存或者数据库,性能会提高。

php session原理就这么简单,只看你运用了。

至于说cookie代替session就会提高,那是没什么依据的。cookie数据量有限制,而且cookie数据量大了以后,直接消耗你的带宽流量。

codeigniter就是把session放在了cookie.

这样做有明显的弊端, 一是网络流量增大, 渲染速度明显变慢,

二是客户端cookie的容量有限, 你不能存放过大的数据.

其实还有一个办法把session放入内存, 不过这种代价比较大, 对服务器内存要求就高了. 也有弊端啊...

PHP用session_start生成的session_id不能保证绝对惟一,但能做到相对惟一,也就是发生冲突的几率比较低.
PHP的session_id串是怎样生成的,冲突的概率有多大,以及容不容易被别人计算出来.
生成算法可以查看php-src/ext/session/session.c里面的函数php_session_create_id.
https://github.com/php/php-src/blob/master/ext/session/session.c
分析源码后我们可以得出结论,PHP默认的session_id生成算法还是比较随机的,
PHPSESSID由用户IP,服务器时间戳,随机数哈希而成.
除非攻击者都够同时猜中用户IP/时间/随机数,然后做哈希,否则很难伪造一个真实存在的PHPSESSID.
从中我们也学到了如何生成一个相对唯一的串,同时了解到了PHP的session存在的安全性问题.
不过,像WordPress并没有采用PHP提供的Session支持,而是自己建立的一套Cookie方案,
Cookie的生成算法跟wp-config.php里自定义的KEY和SALT有关,伪造Cookie更难,因为每个WordPress实例的KEY和SALT都不相同.
SESSION的回收是在每次访问页面的时候进行的:
回收的机率 = session.gc_probability/session.gc_divisor,默认是1/1000.如果设置为1,
则每次超过了SESSION的生存周期(session.gc_maxlifetime,默认是1440秒也就是24分钟)去访问的话,SESSION一定会被回收.
客户端每访问一次SESSION中的变量,SESSION文件的访问时间就会进行更新.
每次访问都是根据客户端存储的SESSIONID去请求服务器中存储的唯一的SESSION.
当客户端的cookie过期后,就无法知道要访问的是哪一个SESSION,尽管此时服务器上的SESSION文件还没有被过期收回,这样就会造成服务器资源的浪费.
如果用户是通过点击"退出"按钮退出系统,这时程序可以注销掉cookie和session.
如果用户是直接没有通知系统退出,保存session_id的即时cookie在浏览器关闭后自动过期,sess_文件则只能依赖PHP回收了.

PHP的session采用被动的回收机制,过期的session文件不会自己消失,而是通过请求触发"回收"来处理过期的session.
这时可以定时(crontab)手动删除过期的session:
cd /path/to/sessions
find -cmin +24 | xargs rm 找出24分钟前的文件并删除.

PHPSESSID这个cookie的过期时间可以用session_set_cookie_params进行设置,这样就可以在浏览器关闭重新打开后保持PHPSESSID这个cookie有效:
http://php.net/manual/zh/function.session-set-cookie-params.php
顶部