session(会话机制)主要是用来在客户端与服务器之间保持状态的解决方案。随着访问量的不断增加,session的性能会有很大的影响。
在 php 中,session 会存放在临时文件夹中,例:/tmp,因为session的读写涉及到大量小文件的随机读写,并且是集中在一个目录下,IO 也急剧升高。常见的 session 优化有以下几种:
1.将 /tmp 挂载为内存中,具体操作参考网上资料;
2.将 session 的存放目发录分为多级,主要是修改 php.ini 里的 session.save_path 的参数,这个具体也可参考网上资料;
3.mysql 存储,这样做的好处就是可以多服务器共享 session,但好像性能不是很好,具体没测过;
4.memcached 存储,memcached 是目前最流行的缓存服务器,memcache php客户端最近的版本中都内置支持 session,存放在 memcache 速度快,memcache本身也有过期机制,不用额外再进行垃圾回收的处理,但 memcache 采用的是内存做存储,如果服务器出现down机数据就会丢失,但根据平时的检测,down机很少出现。
5.还可以将 session 采用 TokyoTyrant 存放,TokyoTyrant 只是一个网络接口服务器,后面的存储采用的是 Tokyo Cabinet,Tokyo Cabinet 的效率不用怀疑,网上也有很多文章进行过介绍,而且还支持主从同步,它是将数据存放在硬盘上,不用担心数据丢失,下面来介绍一下用 TokyoTyrant 搭建 session 服务器。
#安装 Tokyo Cabinet wget http://1978th.net/tokyocabinet/tokyocabinet-1.4.45.tar.gz tar zxvf tokyocabinet-1.4.45.tar.gz cd tokyocabinet-1.4.45 ./configure --enable-off64 #32位系统需要 --enable-off64,以让它支持大于2GB的文件 make make install cd ../ #ttserver运行时,支持一些扩展脚本,这里采用lua脚本,所以需要lua的支持,安装 lua wget http://www.lua.org/ftp/lua-5.1.4.tar.gz tar zxvf lua-5.1.4.tar.gz cd lua-5.1.4.tar.gz #要根据系统而定,直接make它会有提示 make linux make install ln -s /usr/local/bin/lua /usr/bin/lua cd ../ #安装Tokyo Cabinet 的 lua 扩展 wget http://1978th.net/tokyocabinet/luapkg/tokyocabinet-lua-1.9.tar.gz tar zxvf tokyocabinet-lua-1.9.tar.gz cd tkoyocabinet-lua-1.9.tar.gz ./configure make make install cd ../ //安装 Tokyo Tyrant wget http://1978th.net/tokyotyrant/tokyotyrant-1.1.40.tar.gz tar zxvf tokyotyrant-1.1.40.tar.gz ./configure --enable-lua --with-lua make make install cd ../
还需要一个 expire.lua 文件,这个文件用于定时将过期的 session 清理。代码如下:
function expire() local args = {} local cdate = string.format("%d", _time()) table.insert(args, "addcond\0x\0NUMLE\0" .. cdate) table.insert(args, "out") local res = _misc("search", args) if not res then _log("expiration was failed") end print("rnum=" .. _rnum() .. " size=" .. _size()) end
这里我在 /etc/ttserver/ 下建立了 expire.lua 文件,保存上面的代码。
建立 /data/ttserver/session1 文件夹,并让该目录具有写权限,同样再建 /data/ttserver/session2、/data/ttserver/session3 文件夹。
现在就可以起动 ttserver 了,在命令行下输入:
ttserver -host 127.0.0.1 -port 11221 -ext /etc/ttserver/expire.lua -extpc expire 5.0 -thnum 8 -dmn -pid /data/ttserver/session1/ttserver.pid -log /data/ttserver/session1/ttserver.log -le -ulog /data/ttserver/session1/ -ulim 128m -sid 1 -rts /data/ttserver/ttserver.rts '/data/ttserver/session1/sessions.tct#idx=key:lex#idx=x:dec#dfunit=8'
-ext 参数:指定扩展脚本,这里是用于定时清理 session
-extpc 参数1 参数2:参数1,为调用扩展脚本里的函数名;参数 2 为执行频率。
/data/ttserver/session1/sessions.tct#idx=key:lex#idx=x:dec 是设定存储的文件名,存储格式为 tct,idx 设置索引,这里key、x字段设为索引,lex表示类型是字串,dec表示类型为数字。
其他参数不多讲了,可以参考这里:Tokyo Tyrant(TTServer)系列-启动参数和配置
启动后就可以在 /data/ttserver/session1 目录看到生成了几个文件:
当有数据写入时还将会生成一个 .ulog 文件。
接着可以在本机的 11222、11223 启动 ttserver,分别采用 /data/ttserver/session2、/data/ttserver/session3 目录存储。
用 ps -ef | grep ttserver 可以检测是否存在三个 ttserver 进程。
现在整个服务器环境配好了,开始配置PHP环境:
先去下载 php 访问 ttserver 的客户端,有php源码的,也有 php扩展 so,由于是测试环境,不想去编译模块,就用了php写的客户端,下载地址为:
http://mamasam.indefero.net/p/tyrant/
在 php 的 ttserver 扩展模块中(http://pecl.php.net/package/tokyo_tyrant),已支持 session ,可以参考这里(http://us3.php.net/manual/en/tokyo-tyrant.installation.php)的文档配置就行了,比较简单。
下面以 php 客户端为例,写一个自定义的 session 处理,代码如下:
'127.0.0.1', 'port' => '11221'), array('host' => '127.0.0.1', 'port' => '11222'), array('host' => '127.0.0.1', 'port' => '11223') ); $server_num = 0; function sess_open() { global $server_num; $server_num = crc32(substr(session_id(), 0, 2)) % count($server_array); return true; } function sess_close() { return true; } function sess_read($id) { global $server_array, $server_num; $tt = Tyrant::connect($server_array[$server_num]['host'], $server_array[$server_num]['port']); $values = $tt->get($id); if ( is_array( $values ) && isset( $values['val'] ) ) { return $values['val']; } } function sess_write($id, $value) { global $server_array, $server_num; $tt = Tyrant::connect($server_array[$server_num]['host'], $server_array[$server_num]['port']); $values = array( 'val' => $value, 'x' => time() + SESS_EXPIRE ); return $tt->put($id, $values); } function sess_destroy($id) { global $server_array, $server_num; $tt = Tyrant::connect($server_array[$server_num]['host'], $server_array[$server_num]['port']); return $tt->out($id); } function sess_gc() { return true; } ini_set('session.save_handler', 'user'); session_set_save_handler( "sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc"); session_start(); // 当设完 session 后,可以注下这一行代码。直接输出 session 里的内容 // 放着过 5 分钟以后再去刷新页面,session 的值就为空了 $_SESSION['key'] = 'hello world'; var_dump($_SESSION['key']); ?>
By xhttp.cn 整理:http://www.xhttp.cn/2010/06/16