<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>程默的博客 &#187; session</title>
	<atom:link href="http://blog.chacuo.net/tag/session/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.chacuo.net</link>
	<description>web原理、web架构、web安全、web性能、服务器性能、服务器架构、服务器安全;你不能预知明天，但你可以利用今天。你不能样样顺利，但你可以事事尽力!</description>
	<lastBuildDate>Mon, 31 Aug 2020 15:33:40 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>php session阻塞页面分析及优化 （session_write_close session_commit使用）</title>
		<link>http://blog.chacuo.net/168.html</link>
		<comments>http://blog.chacuo.net/168.html#comments</comments>
		<pubDate>Thu, 06 Jun 2013 11:17:59 +0000</pubDate>
		<dc:creator>程默</dc:creator>
				<category><![CDATA[web原理]]></category>
		<category><![CDATA[web性能]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://blog.chacuo.net/?p=168</guid>
		<description><![CDATA[这个问题很多做php开发朋友应该都有遇到过，一个启用了session_start 页面，由于执行时间过长。导致 [...]]]></description>
				<content:encoded><![CDATA[<p>这个问题很多做php开发朋友应该都有遇到过，一个启用了session_start 页面，由于执行时间过长。导致通一个用户访问，另外一个很简单的启用session_start页面一直阻塞着。 直到第一个页面执行完了。第二个页面就可以读取。这个就是，我们常说的，session阻塞机制。</p>
<ul>
<li>
<h3><strong>我用file 存放用户session</strong></h3>
</li>
</ul>
<p>session默认以文件保存，当一个用户访问session_start页面后，这个时候，就会默认创建一个包含session_id文件名，并且这个时候，会对文件进行锁定。如果这个用户点击链接，又访问一个该站session_start网页。这是，由于session_id一样，这个页面也有读取锁定该用户存放session文件。 由于，第一个页面没有执行完，它一直锁定了该文件。 第2个页面就不能获取锁，一直处于等待状态。</p>
<p>这样一个看似小的问题，实际上，如果网站上面有大量用户访问，会导致session读取文件一直阻塞等待着。用户浏览器一直跟服务器保持连接，会消耗很多服务器资源。web服务器活跃连接数也会增大，可能很快就会耗费完连接资源，出现拒绝服务器。</p>
<ul>
<li>
<h3><strong>我用memcache 存放用户session</strong></h3>
</li>
</ul>
<p>用memcache保存用户session，相比读取文件有很大速度提升。而且可以做到多服务器共享session。确实很方便，这个时候，我们发现不会出现用文件保存session锁定清理。memcached读取时候，是共享的，不会出现等待。但是，我们会发现，memcached连接数，还是会保持着。并且，连接数会增加，如果这个时候，你设置的memcached连接数过小，你会发现，很快memcached就挂死了。 这也是，做memcache接管session时候，经常遇到问题。 有时候，web服务器很多，session(memcache)很少。发现memcache莫名其妙死掉，可能跟这个有关系。太多反映很慢的页面(启动session)，会导致占用了大量memcached连接数。</p>
<ul>
<li>
<h3><strong>改变session使用习惯、优化调用方法</strong></h3>
</li>
</ul>
<p>其实，通过file或者session，如果处理耗时页面，都会带来服务器资源很大消耗。其实我们一般写入session或者读取时候，如果自己能够控制。用完了，就关闭掉文件锁，或者mem连接。就会自动释放资源，其实，php里面的：session_write_close，session_commit 函数就能做到改功能。我们看下下面代码执行过程：</p>
<blockquote><pre style="text-indent: 0px" lang="php">&lt;?php
ini_set('session.save_path','/tmp/');

function open($save_path, $session_name)
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
	return(true);
}
function close()
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
	return(true);
}
function read($id)
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
}
function write($id, $sess_data)
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
	return(true);
}
function destroy($id)
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
	return(true);
}
function gc($maxlifetime)
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
	return true;
}
session_set_save_handler(&quot;open&quot;, &quot;close&quot;, &quot;read&quot;, &quot;write&quot;, &quot;destroy&quot;, &quot;gc&quot;);
register_shutdown_function('test');

function test()
{
	echo __FUNCTION__,&quot;&lt;br /&gt;&quot;;
}
session_start();
echo 'aaaaa',&quot;&lt;br /&gt;&quot;;</pre>
</blockquote>
<p>&#160;</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image3.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb3.png" width="760" height="486" /></a> </p>
<p>启动”session_start” 会自动执行,open,read函数，然后页面执行完，会执行shutdown函数，最后会把session写入进去，然后执行close关闭文件。从session_start 到页面结束，会一直锁定文件或者保持连接的。</p>
<p>我们如果 执行完session_start后，执行”session_commit();” 看看结果</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb4.png" width="495" height="202" /></a><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image5.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb5.png" width="395" height="271" /></a>&#160; </p>
<p><strong>执行过程：</strong>执行commit后，直接会调用，wirte,close操作。直接关闭文件或者关闭连接(memcache)了。 </p>
<p><strong></strong></p>
<ul>
<li>
<h3><strong>我们的问题</strong></h3>
</li>
</ul>
<h3>1.我们页面有多次写入，怎么样操作？</h3>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb6.png" width="472" height="228" /></a> <a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image7.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb7.png" width="414" height="170" /></a> </p>
<p>&#160;</p>
</p>
</p>
<p><a href="http://blog.chacuo.net/wp-content/uploads/2013/06/image8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.chacuo.net/wp-content/uploads/2013/06/image_thumb8.png" width="474" height="310" /></a> </p>
<p>第一次写入后，然后提交，再次打开写入，然后再次提交。我们发现，2次数据都保存到用户session中了。</p>
<p>&#160;</p>
<ul>
<li>
<h3><strong>我们来总结下吧</strong></h3>
</li>
</ul>
<p>1.只读取session页面，建议打开后，就直接commit，这是$_SESSION变量已经生成了。</p>
<p>2.有对session进行写入页面，建议修改完$_SESSION后，直接调用commit</p>
<p>3.多次打开并且写入，这个不建议使用，比较打开文件，写入都是耗费时间的。如果能一次搞定的，就不要做多次了。 除非，中间执行很耗时的业务。 </p>
<p>后记：其实，使用完session，随手commit也不是坏事，养成习惯后。可以节省性能，减少服务器开销。是个不错选择！欢迎大家交流！</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chacuo.net/168.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
