内容简介:最近在一个基于 Web 的 IM 项目中,我采用异步向服务器发起请求拉取最新的聊天内容,服务器端通过 PHP 处理拉取请求,拉取过程是用 10 次循环查询数据库是否有最新的聊天内容。如发现新内容,则立即向浏览器输出,并结束掉本次请求的进程。在这 10 次的循环中,每次查询数据库后,均通过 Sleep 函数让进程暂停 1 秒,那么这个 PHP 进程可能会在服务器端保持 10 秒。在测试过程中,我发现当这个拉取请求运行期间,其他向服务器端 PHP 发起的请求,均受到影响,响应变的非常慢。经过一系列的排查,问题
最近在一个基于 Web 的 IM 项目中,我采用异步向服务器发起请求拉取最新的聊天内容,服务器端通过 PHP 处理拉取请求,拉取过程是用 10 次循环查询数据库是否有最新的聊天内容。如发现新内容,则立即向浏览器输出,并结束掉本次请求的进程。在这 10 次的循环中,每次查询数据库后,均通过 Sleep 函数让进程暂停 1 秒,那么这个 PHP 进程可能会在服务器端保持 10 秒。
在测试过程中,我发现当这个拉取请求运行期间,其他向服务器端 PHP 发起的请求,均受到影响,响应变的非常慢。
经过一系列的排查,问题始终得不到解决,但当把代码中涉及到 SESSION 的部分全部跳过时,情况发生了变化,所有 PHP 进程都恢复正常的响应速度了。由此,联想到问题可能出在了 SESSION 阻塞机制上了。
关于 PHP 的 SESSION 阻塞机制,我们要先了解其工作状态,先看如下代码:
<?php // 第 1 次打印 SESSION 状态 echo 'Status(1):' . session_status() . '<br>'; // 1 // 开启 SESSION session_start(); // 第 2 次打印 SESSION 状态 echo 'Status(2):' . session_status() . '<br>'; // 2 $_SESSION['test'] = 'hello world'; // 等价于 write and close session_commit(); echo $_SESSION['test'] . '<br>'; // 第 3 次打印 SESSION 状态 echo 'Status(3):' . session_status() . '<br>'; // 1 ?>
上述代码输出的结果如下:
Status(1):1
Status(2):2
hello world
Status(3):1
通过 session_status() 这个函数可以得到 SESSION 的状态,返回值含义如下:
0 – 会话是被禁用的。
1 – 会话是启用的,但不存在当前会话。
2 – 会话是启用的,而且存在当前会话。
当上边的代码中第一次通过 session_status() 函数获取 SESSION 状态时,返回值为1,代表当前 SESSION 功能是可用的,但还没有处于激活状态的会话。
用我们非常熟悉的 session_start() 函数开启会话后,再次用 session_status() 函数获取状态,发现返回值已经变为2,这说明当前已经有了激活状态的会话。
重点在 session_commit() 这个函数被执行后,再次获取状态,返回值又变为1。
PHP 的 session_start() 函数执行时相当于完成了会话的 open 和 read 两个步骤,而 session_commit() 执行时相当于进行了会话的 write 和 close 两个步骤,与 session_write_close() 函数作用是一致的。
回到最初遇到的问题上,当 PHP 的 SESSION 开启后,进程会对会话的临时文件加锁,以保证同一时刻此文件只被一个进程修改。此时,如果会话没有 close 而其他进程又开启了会话,后来的进程就会被 PHP 暂时阻塞,等待临时文件解锁。
接下来看两段代码
a.php
<?php session_start(); $_SESSION['t1'] = time(); sleep(10); echo $_SESSION['t1']; ?>
b.php
<?php session_start(); $_SESSION['t2'] = time(); echo $_SESSION['t1']; ?>
我们将上边两段代码分别保存为文件 a.php 和 b.php,首先运行 a.php,紧接着运行 b.php,我们发现在 a.php 没有结束还处于 sleep 状态时,b.php始终被阻塞在那里迟迟无法输出结果,原因就是上边我们分析的会话临时文件被加锁,后来的进程被暂时阻塞的问题。
为了解决这个问题,我们可以在进程进入 sleep 前,通过 session_commit() 函数将会话 close 掉,从而让当前进程解锁会话临时文件,以便让其他进程获得文件的锁。
修改后的 a.php 代码如下:
<?php session_start(); $_SESSION['t1'] = time(); // write and close session_commit(); sleep(10); echo $_SESSION['t1']; ?>
按上边的代码修改 a.php 后,我们再次在浏览器中运行两个文件,a.php 在 sleep 状态下,b.php 已经可以很正常的运行了。
阳光部落原创,更多内容请访问 http://www.sunbloger.com/
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 深入理解 Java 锁与线程阻塞
- HBase Memstore数据刷写与阻塞机制深入剖析及参数优化-OLAP商业环境实战
- Node.js 指南(阻塞与非阻塞概述)
- Node.js 回调函数 阻塞与非阻塞
- 明明白白学 同步、异步、阻塞与非阻塞
- 从 Linux 源码看 socket 的阻塞和非阻塞
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
系统分析与设计方法
惠滕 / 孙慧、肖刚 / 机械工业出版社 / 2004-9 / 69.00元
本书是介绍信息系统分析和设计原理、方法、技术、工具和应用的力作,自问世以来,广受欢迎,以至于一版再版,延续至今。 本书采用一个完整的案例研究,以整个信息系统构件(基于Zachman框架)和信息系统开发生命周期(FAST方法学)为主线,详细探讨了系统开发生命周期的前期、中期和后期以及跨生命周期的活动。另外,书中第一章都提供了大量的练习题、讨论题、研究题和小型案例,以加深读者对书中所述理论的实际应用和......一起来看看 《系统分析与设计方法》 这本书的介绍吧!