同一个服务器上的不同项目要注意session的死锁问题
来源:互联网 发布:淘宝起名字 编辑:程序博客网 时间:2024/05/18 02:26
最近做一个CMS的项目,需要调用服务器上的另一个项目提供的API接口,结果发现总是调用不成功。
但是在开发环境下却是好的,只在测试环境下以及线上环境上不行。
我在cms上用curl来调用另一个项目的api接口,需要传一个sessionId过去,另外就是认证的key以及项目名称/时间,另外又做了一个所有元素的md5,作为api验证数据完整性以及核对认证key。
结果跟踪调试的过程中,发现调用的结果总是false,但是用日志跟踪的话,发现api服务器上已经将返回值写入到日志文件中,但是cms调用的api接口返回结果在这之前已经返回false了,这个返回值是curl_exec方法返回的。
session_start();
$time = time();
$sessionId = session_id();
$token = $this->makeToken($sessionId,$time);
$url = API_SERVER_URL.'/api/doctor/getSomeInfo';
$post = ['appId'=>'al','time'=>$time,'token'=>$token,'sessionId'=>$sessionId,'type'=>'1','page'=>1,'pageSize'=>6];
$content = "in getStarDoctors(),url=$url,post:".json_encode($post)."\r\n";
file_put_contents('/tmp/aaa.log',$content,FILE_APPEND);
$result = $this->curl_post($url,$post);
$content = "in getStarDoctors(),result:".var_export($result,TRUE)."\r\n";
file_put_contents('/tmp/aaa.log',$content,FILE_APPEND);
$content = "in getStarDoctors(),result:".json_encode($result)."\r\n";
file_put_contents('/tmp/aaa.log',$content,FILE_APPEND);
echo $result;
return;
查询了半天,也不知道问题出在了哪里,开发服务器上的日志显示顺序都是正确的,返回结果也是正确的。
两边做了一下对比,开发服务器上的cms调用的同一台机器上的另一个项目,测试服务器上的cms也是调用的同一台服务器上的另一个项目;
这是为什么呢?纠结中......
后来我们就换一下思路,让开发服务器上的cms调用测试服务器上的api接口,结果发现返回结果正常而不是false;
然后又让测试服务器上的cms调用开发服务器的api,也没有问题;
基本上锁定问题就处在测试服务器上;然后这个问题还是没有解决方法;然后我们想只要线上环境没有这个问题就行,
所以线上环境上测试,结果发现线上环境也不行,cms也调不通api接口,看来这个问题非解决不可了。
然后找高手看一下好像也没有太多的头绪,正好旁边一个同事用xhprof跟踪调用的过程,结果发现问题出在api接口的session_start()上了,这一句就要执行8秒的时间
然后就分析一下原因,同一台服务器上的session,php配置的session存储方式为文件方式,cms项目写了session之后没有及时关闭写入,导致cms占用了session文件
因为该文件cms项目正在写,所以api接口无法读取,必须等curl调用结束之后,我这一个curl请求结束之后,然后api服务器才会执行接下来的语句。
所以我们终于找到了原因,也很快找到了解决方法;也就是在cms项目的session_id()之后,立即调用session_write_close(); 来结束写进程,这样api项目就能很快地读取到该session文件了。
结合了PHP的Session机制,找到了阻塞的原因。由于PHP的Session信息是写入文件的,1个客户端占有1个session文件。因此,当 session_start被调用的时候,该文件是被锁住的,而且是以读写模式锁住的(因为程序中可能要修改session的值),这样,第2次调用 session_start的时候就被阻塞了。
所以同一台服务器上的不同项目一定要注意session的死锁问题。
其实同一个项目中的不同代码,如果一个页面调用了session_start()方法,然后他转到的另一个页面也调用了session_start()方法,也可能会出现这种死锁情况。
因为上一个页面没有结束时,就会阻塞下一个页面使用session_start()方法,所以最好的方式是对于session写完值之后立即调用session_write_close()进行关闭。然后下一个调用session_start()方法的话就不会再受影响了。session_commit()是session_write_close()方法的别称,写完后调用session_commit()也可以。
至于开发服务器上为什么能调通呢?我们发现cms项目的session是保存到memcache中的,session_write_close()不影响并发写,所以不会造成死锁的。
session保存到memcache中的话,不会出现并发读的问题,但是会导致memcache中的连接被占用,每一个session_start()都会创建一个连接,这会导致memcache性能下降的,所以这里也应该调用session_write_close()方法,关闭session才好。
- 同一个服务器上的不同项目要注意session的死锁问题
- 同一个tomcat不同项目的session共享问题
- 同一个tomcat不同项目的session共享问题
- Tomcat 同一服务器上 不同web项目共享session的
- 不同的域名指向同一个主机上的不同项目
- 同一机器上不同应用服务器之间的Session问题
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 在同一个tomcat下,不同的web项目共享session
- 如何给同一个电脑上的不同项目设置不同的name和email
- 同一个项目接收请求的时候每次获得的session都不同
- 关于同一tomcat服务器下2个不同的web项目如何共享session的问题
- 同一个服务器,不同表数据的复制
- c++实验6-数组合并
- Android开发:ListView、AdapterView、RecyclerView全面解析
- 自定义Listview适配器的优化
- 我没有解决的迷之错误
- 数据结构栈的操作
- 同一个服务器上的不同项目要注意session的死锁问题
- Eclipse安装Swing插件
- 【OpenCV】一种基于阈值的图片中的文字分割
- 动态规划专题总结
- 使用ngrok暴露内网服务到公网
- SIP协议学习
- 未来发展的方向
- onethink后台上传图片,同一张图只能上传一次的问题
- CodeForces 246A. Buggy Sorting【思维】