VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > PHP >
  • 解决PHP中session阻塞问题的办法

最近小峰在开发项目的时候遇到一个问题就是阻塞问题。用的是thinkphp框架,利用ajax请求一次操作,在ajax没有返回结果前,相同程序,其它操作是无效的。然后网上一查,有人和我有一样的问题,下面把该解决方法分享出来。

当同时向服务端发现若干HTTP请求,有时你会发现这些请求可能并非并发完成的,服务器对这些请求进行了排队处理,产生了所谓的PHP阻塞现象。最有可能是脚本进行了session数据的读写,PHP中session默认使用文件系统进行存储的,当进行读写session文件操作时,存储session的文件处于锁定状态,此时其他需要读写session数据的请求需要等待前一个请求完成后才会进行,从而导致PHP阻塞的发生,庆幸的是PHP提供了session_write_close()函数来结束当前session并写入数据。

session阻塞简单演示

创建2个php文件:session_a.php,session_b.php。

  1.  <?php 
  2. // session_a.php 
  3. session_start(); 
  4. $_SESSION['a'] = date('H:i:s'); 
  5. // session_write_close(); 
  6.  
  7. sleep(5); 
  8. echo $_SESSION['a']; 
  9. //phpfensi.com 
  10.  <?php 
  11. // session_b.php 
  12. session_start(); 
  13. $_SESSION['b'] = date('H:i:s'); 
  14. // session_write_close(); 
  15.  
  16. sleep(5); 
  17. echo $_SESSION['b'];  

同时访问这2个脚本,你会发现,其中一个脚本比另一个延迟了5秒。而当我们将文件中的session_write_close()函数注释取消掉后,再来同时访问发现2个脚本可以同时执行了。

session锁定处理机制

顺便提一下,session_commit()是session_write_close()的别名,即也可以使用前者替代后者。

当session_start()调用时,session处理机制默认会打开或创建一个seesion文件,且会立即给这个文件上了一个锁定状态(locked)。当session_commit()调用时或脚本执行完成后该文件会被解锁(unlocked)。

锁定状态有个重要的影响:同时请求使用了session的PHP脚本,并非并列执行的,而是分离的。如果当用户发起了一个请求,同时发起另一个请求便会被阻塞,直至前一个请求完全完成。

Session锁定的好处

请不要勿以为这所谓的阻塞现象是PHP的BUG,当然不是,相反有些时候分离执行才是正确的做法。考虑一下购物车案例:

用户发起A请求,脚本读取用来显示购物车物品的session数据;

在A请求完成之前,用户便点击了“加入购物车”按钮,发送了个B请求;

B等待A请求完成,然后向session中新增数据;

如果没有对session进行锁定会发生什么?

B没有等待A完成,读取并写入session数据;

A请求完成并写入之前读取的session数据,覆盖了上述B写入的数据;

所以,我们在使用session时应当考虑当前实际环境。

ThinkPHP如何解决session阻塞

最近开始使用国内的PHP框架ThinkPHP,便遇见了阻塞问题,因为没仔细看官方文档,调试许久未果,差点一怒之下放弃该框架,后发现配置项里有个“SESSION_AUTO_START”配置,用于自动加载session,果断设置为FALSE,一切恢复正常。

在需要使用session的时候,可以使用PHP自带函数:

  1.  session_start(); 
  2. //... 
  3. session_commit();   // 或session_write_close() 
  4. 也可以用TP风格方式: 
  5.  
  6. session('[start]'); 
  7. //... 
  8. session('[pause]'); 
  9.  

出处:http://www.phpfensi.com/php/20181020/11391.html


相关教程