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

 更新时间:2016年11月25日 17:36  点击:2144
本文章来为各位介绍关于解决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。

 <?php
// session_a.php
session_start();
$_SESSION['a'] = date('H:i:s');
// session_write_close();

sleep(5);
echo $_SESSION['a'];

 <?php
// session_b.php
session_start();
$_SESSION['b'] = date('H:i:s');
// session_write_close();

sleep(5);
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自带函数:


 session_start();
//...
session_commit();   // 或session_write_close()
也可以用TP风格方式:

session('[start]');
//...
session('[pause]');

memcache是一套分布式的高速缓存系统,在Drupal中我们可以利用Memcach提高Drupal应用性能,本文是我们总结的Memcache的hash策略及配置。

Memcach是web应用/Drupal应用性能提高的利器,近期在使用Memcache中,发现有很多小问题,因此作者特意总结了几个,放上来供大家参考使用。

1. Memcache和Memcached的区别

这个是历史问题,但是,言而总之:名字长的更牛逼!  

所以,推荐使用memcached。
另外,memcached有很多新特性,包括getMulti/setMulti、支持存储object、支持count+1操作,都会比memcache的好用一些,可以试试,或许以后支持更多的操作,赶上redis。。

Drupal大学上关于memcache的问答:http://../apachesolr_search/memcache


如下(摘自德问):

#Memcache
$m = new Memcache();
$m->addServer('localhost', 11211);
$v = $m->get('counter');
$m->set('counter', $v + 1);
#由于get/set这两个动作无法作为一个原子来操作,所以当多个进程同时处理时,
#会出现丢失的可能,更让人恼火的是,你根本就不知道什么时候出现丢失。

#Memcached
$md = new Memcached();
$md->addServer('localhost', 11211);
$v = $md->get('counter', null, $token)
$md->cas($token, 'counter', $v + 1);
#cas是Memcached版本里提供的功能,说白了就是一个乐观锁的功能,
#如果你把$token的值var_dump出来,就会发现$token其实就是一个版本号,
#如果通过get得到的$token版本号在cas的时候不对应,就说明已经有别的操作更新了,
#此时cas操作会失败,至于如何继续操作,就看你自己了

两者的区别如下,下面是Memcache的方法:

memcache
下面是memcached的方法:
memcached

2. Memcache的哈希策略

    常规的hash策略是取模,比如key=10, 有两台服务,就10%2=0,算出该值分布在第一台服务器上。
    那么缺点也很明显,比如服务器增加一台,之前的分布式策略全完蛋。

因此,业界需要更牛逼的算法~

一致性hash算法隆重登场!

简单说来,一致性hash算法就是先把服务器也通过某一个特征(如IP/MAC地址)hash一下,这样服务器会按照分布(可能不均匀)在一个范围,然后把key再hash一下,然后看key最近的下个服务器作为该key的存储bin。
这样,如果增加一台服务器,重新分配的key只是分布再新增的这个服务器和上一个最近的服务器之间的key,其余的都不变。

初步的服务器分布:

hash-1

增加服务器的分布:
hash-2

上面的描述的是白话,可能比较拗口,笔者文字水平有限,详情见下面的链接:

http://blogread.cn/it/article/5271
http://blog.csdn.net/kongqz/article/details/6695417

3. Memcache的hash策略配置

Memcache安装完成之后,可以设置哈希策略,memcache.hash_strategy。目前有standard模式和consistent模式。standard模式其实就是%,即取模。而consistent,就是hash的一致性算法。

在Memcache中,hash策略在PHP.ini文件中设置

[Memcache]
Memcache.allow_failover = 1
……
……
Memcache.hash_strategy =consistent
Memcache.hash_function =crc32

在Memcached中,hash策略在PHP的参数中设置:

mem = new memcached();
$mem-&gt;setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
$mem-&gt;setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE,true);

 

4. 后记

因此正常情况下,推荐使用一致性哈希算法,但凡事无绝对,比如一个小的站点,memcache的服务几乎永不会增加,这是用常规的standard的算法也是比较推荐的,毕竟一致性算法存在一个均匀分布的问题(可能已经解决了。。)

下面我们一起来看看关于BBSMAX发布部署提示”default.aspx”中模版变量”PageTitle”不存在,请检查模版解决办法。
今又想起了bbsmax,拿出来试验测试下!翻出了bbsmax1008源码包,运行发布,再部署运行,出现“模板文件”E:\bbsmax\max-templates\mobile\forums\default.aspx”中模版变量”PageTitle”不存在,请检查模版。”错误。

 

default.aspx中模版变量"PageTitle"不存在,请检查模版图示

 

万思不得其解,因之前运行部署是可以的,搜索找了下答案,靠谱答案如下:
出现这种情况,原因可能是:
1、所有的页面都要继承自 BbsPageBase
2、aspx页面放在 max-templates目录下的某个模板目录下
3、aspx.cs代码文件必须放在  _codes目录下的对应 max-templates 的子目录

 

说了几种情况,没太看明白!后面试了把MaxLabs.bbsMax.Web文件夹里的_codes文件夹复制到站点根目录下,再次编译果然正常运行。(经测试,前台问题是解决了,但后台也出现类似错误,寻找解决中)

 

如果是第一次发布部署,可以通过bbsmax项目助手发布,就不会存在此问题,并且带install.aspx安装程序!
现在QQ互联登录在许多的网站都集成了,但今天小编碰到在QQ互联登录时出现redirect uri is illegal(100010)错误,下面我们来看看问题的一个解决办法。
大概2015年3月低,腾讯QQ互联开发平台调整了有关QQ登录应用回调地址填写规则,用来修复QQ登录过程因回调地址的漏洞可能导致存在的安全问题。

 

博主接触这块较多,但也是四月才了解此事,从4月起,所有新申请的QQ互联应用,回调地址都不能只填写根域名,比方:unvs.cn,这样是不允许的。

 

解决方法:必须要填写你应用QQ登录返回的真实回调地址页面,必须带有HTTP://开头、及页面名称结尾,如:http://www.unvs.cn/oauth/default.aspx。

 

否则点击QQ登录图标后,跳转到QQ平台会显示“redirect uri is illegal(100010)”错误代码,如图:
QQ登录回调地址错误redirect uri is illegal(100010)

 

修改方法与位置
1、进入QQ互联平台:http://connect.qq.com/

 

2、管理中心–我的应用–应用基本信息,回调地址修改,如下图:
QQ互联登录回调地址正确填写

 

3、当有多个回调地址,怎么办?如果你的域名分带www、不带www,那么回调地址应该要填写2个,正确填写方法:两个回调地址页面以分号分割开,多个回调地址同理,如:http://www.unvs.cn/oauth/default.aspx;http://unvs.cn/oauth/default.aspx
QQ互联登录多个回调地址正确填写

 

最后,再举例说两个常用电商程序的回调地址填写,ecshop程序的第三方登录插件,回调地址填为:http://域名/user.php ,hishop程序的QQ登录回调地址填为:http://域名/openid/OpenIdEntry_hishop.plugins.openid.qq.qqservice.aspx 等等。

 

好了,就总结这么多,其实文章一句话就可以概括,但还是希望能清楚的说明缘由及解决方法与操作,希望可以帮助到各位,
本文章为各位总结了关于php提示”Cannot send session cache limiter ? headers already sent by”错误解决办法。


运行PHP页面,提示“Cannot send session cache limiter – headers already sent by()”或者"function session_start()"错误,让人非常头痛。因为这不是第一次遇到了,为了加深印象,把问题原因分析及解决方法详细写下来,分享给大家。

问题分析:

记得第一次遇到这个问题时,谷歌了很多答案,也有很多种解决方法,但出现这个问题大部分最根本的原因是:当在运行session_start();时是不能有任何输出,而这之前页面已经有出现空行现象,或可以说页面是含有DOM编码的UTF-8页面。

查看页面是否含有DOM编码方法:

1、使用Dreamweaver软件打开页面,查看页面属性(修改-页面属性-标题/编码),查看“包括Unicode签名BOM”项前面是否打勾;

2、记事本打开,另存为时,编码格式为ANSI则不含有DOM,若为UTF-8,基本肯定含有。

解决办法:

通过工具,如:editplus、ultraedit等工具,去掉DOM行即空白行即可解决,具体步骤如下

 

步骤:通过UE打开页面–文件–另存为–格式选择“UTF-8无BOM”–保存,即完成了UTF-8页面去BOM头,再不会出现页头空行情况。
如图所示:
 

 

 


其它解决方法:

1、页面头部加上:ob_start();//偶尔碰到失效;
2、新建页面,将代码COPY过去,这个方法有时也管用,注意GBK还是UTF-8编码(通常由GBK另存为UTF-8编码时会默认带DOM编码);
3、另一种情况服务器PHP配置问题:修改php.ini中的 session.auto_start = 0 为 session.auto_start = 1;
4、基本上面的可以解决这个问题,还有些很少见的非常规方法,如果不能解决,大家只能谷歌了。

[!--infotagslink--]

相关文章

  • 409错误是什么 http 409错误怎么解决

    409错误是什么?http 409错误怎么解决呢?不少站长在遇到这个错误代码之后都一筹莫展,本次一聚教程网为大家带来了详细的说明,快来看看吧。 409错误是什么: HTTP 40...2017-01-22
  • PHP session_start()很慢问题分析与解决办法

    本文章来给各位同学介绍一下关于PHP session_start()很慢问题分析与解决办法,希望碰到此问题的同学可进入参考。 最近在做东西的时候发现一个问题 有一个接口挂...2016-11-25
  • http 405错误是什么 http 405错误怎么解决

    http 405错误是什么?http 405错误怎么解决?相信很多站长都在找这两个问题的答案,本次小编为大家带来了详细的教程,快来看看吧。 405错误是什么: HTTP 405错误是H...2017-01-22
  • 403错误是什么 403错误怎么解决

    403错误是HTTP状态码的一种,属于“请示错误”,表示服务器拒绝请求。如果在搜索引擎尝试抓取您网站上的有效网页时显示此状态代码,那么,这可能是您的服务器或主机拒绝搜索...2017-01-22
  • 412错误是什么 412错误怎么解决

    412错误是什么?412错误怎么解决?本次一聚教程网将为大家带来详细的介绍,帮助大家全面了解412错误的意思以及解决412错误的方法。 412错误是什么: HTTP 412错误,(Precond...2017-01-22
  • Perl CPAN::Modulelist的解决办法

    今天用CPAN安装Term::ReadLine,报了个这样的错误 Going to read /root/.cpan/sources/modules/03modlist.data.gz Can't locate object method "data" via package "C...2016-11-25
  • 406错误是什么 406错误怎么解决

    HTTP 406错误是HTTP协议状态码的一种,表示无法使用请求的内容特性来响应请求的网页。一般是指客户端浏览器不接受所请求页面的 MIME 类型。 而MIME类型是在把输出...2017-01-22
  • 407错误是什么 407错误怎么解决

    407错误是什么?407错误怎么解决?不少站长都遇到过407错误,下面小编将告诉大家如何处理407错误。 407错误是什么: HTTP 407错误是HTTP协议状态码的一种,表示需要代...2017-01-22
  • 410错误是什么 http 410错误怎么解决

    410错误是HTTP协议状态码的一种,本次一聚教程网将为大家详细介绍HTTP 410错误是什么,以及410错误的解决办法。 410错误是什么: HTTP 410错误是HTTP协议状态码的...2017-01-22
  • HTTP 400错误是什么 HTTP 400错误怎么解决

    每当遇到http错误代码为400,代表客户端发起的请求不符合服务器对请求的某些限制,或者请求本身存在一定的错误,那么HTTP 400错误怎么解决呢?请看下文介绍。 目前400错...2017-01-22
  • PHP传值到不同页面的三种常见方式及php和html之间传值问题

    在项目开发中经常见到不同页面之间传值在web工作中,本篇文章给大家列出了三种常见的方式。接触PHP也有几个月了,本文总结一下这段日子中,在编程过程里常用的3种不同页面传值方法,希望可以给大家参考。有什么意见也希望大...2015-11-24
  • js修改input的type属性问题探讨

    js修改input的type属性有些限制。当input元素还未插入文档流之前,是可以修改它的值的,在ie和ff下都没问题。但如果input已经存在于页面,其type属性在ie下就成了只读属性了,不可以修改。...2013-10-19
  • Mysql常见问题集锦

    1,utf8_bin跟utf8_general_ci的区别 ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的; bin 是二进制, a 和 A 会别区别对待. 例如你运行: SELECT * FROM table WHERE txt = 'a'...2013-10-04
  • Mysql大小写敏感的问题

    一、1 CREATE TABLE NAME(name VARCHAR(10)); 对这个表,缺省情况下,下面两个查询的结果是一样的:复制代码 代码如下: SELECT * FROM TABLE NAME WHERE name='clip'; SELECT * FROM TABLE NAME WH...2015-03-15
  • linux mint 下mysql中文支持问题

    一.mysql默认不支持中文,它的server和db默认是latin1编码.所以我们要将其改变为utf-8编码,因为utf-8包含了地球上大部分语言的二进制编码 1.关闭mysql服务 sudo /etc/init.d/mysql stop 2.修改mysql配置文件 mysql配...2015-10-21
  • PHP分布式框架如何使用Memcache同步SESSION教程

    本教程主要讲解PHP项目如何用实现memcache分布式,配置使用memcache存储session数据,以及memcache的SESSION数据如何同步。 至于Memcache的安装配置,我们就不讲了,以前...2016-11-25
  • Jrebel启动失败解决方案详解

    这篇文章主要介绍了Jrebel启动失败解决方案详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-07
  • 详解C#中的session用法

    这篇文章主要介绍了C#中的session用法 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • Python3使用Selenium获取session和token方法详解

    这篇文章主要介绍了Python3使用Selenium获取session和token方法详解,需要的朋友可以参考下...2021-02-17
  • 小记一次mysql主从配置解决方案

      今天研究了个开源项目,数据库是mysql的,其中的脚本数据需要备份,由于本人的机器时mac pro,而且mac下的数据库连接工具都不怎么好用,就想着如何利用windows下的数据库连接工具使用,并做相关备份,另外windows系统下的sqlyo...2015-10-21