A-A+

解决PHP中session阻塞问题的办法

2019年05月15日 我爱编程 暂无评论

在开发项目的时候遇到一个问题就是阻塞问题。用的是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. sleep(5);
  7. echo $_SESSION['a'];
  8.  <?php
  9. // session_b.php
  10. session_start();
  11. $_SESSION['b'] = date('H:i:s');
  12. // session_write_close();
  13. sleep(5);
  14. 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. session('[start]');
  6. //...
  7. session('[pause]');
标签:

给我留言

Copyright © 四季博客 保留所有权利.   Theme  Ality

用户登录