|
本文的目的是抛砖引玉,希望能和大家一起交流学习如何解决实际问题。另:本文采用jquery来实现ajax
首先,说明需要解决的问题:
由于一些外部命令对系统资源消耗过大,多用户同时进行操作很容易造成服务器瘫痪,所以需要将用户的请求按提交顺序一个个的单独执行。
解决思路:
当有请求触发时,利用AJAX提交请求,返回列队信息,当列队到达顶点时(即:轮到该用户执行请求了),再接受表单信息或者其他信息。
实现方法:
1、首先需要写一个处理列队的操作。
PHP的部分代码如下:
PHP复制代码
<?php
class Ctl extends Controller
{
...
function queue ()
{
...
//首先判断此用户是否在用户列队数据表中,如果没有在列队中,则添加
$data = array(
'sessId' => $this->session->userdata('session_id'), //这里我用sessionID来规定了某一用户或者说某一操作的唯一标识
'lastActivity' => date('U'));
$this->db->insert('tbl', $data);
$this->db->where("id < {$this->db->insert_id()}");
$query = $this->db->get('tbl');
$count = $query->num_rows(); //得到该用户或该次操作前面还有多少请求在列队中
...
//如果用户在列队中,则更新他的最后活动时间
$data = array(
'lastActivity' => date('U'));
$this->db->where(..);
$this->db->update('tbl', $data);
$this->db->where("id < {...}");
$query = $this->db->get('tbl');
$count = $query->num_rows();
...
$count == 0 ? echo "its your turn" : echo $count;
}
...
}
?>
复制代码
2、接着需要写一个ajax来提交执行请求.
Javascript的部分代码如下:
JS复制代码
$('#button').click(function(){
if(confirm("您确定要执行XX") == TRUE)
{
$.ajax({
url:"http://your/domain/ctl/queue",
type:"GET",
cache:false,
dataType:"text", //当然用XML,JSON,HTML都可以,为了简单实现功能,我用text举例
success:function(queue_info){ //queue_info是用来接收ctl/queue返回的信息
if(queue_info == "its your turn")
{
//.... 如果返回信息为列队顶部,则执行....
}
else
{
alert("您前面还有" + queue_info + "位用户在排队,轻稍候...");
}
}
});
}
});
复制代码
经过以上的两步会发现,执行请求通过AJAX只执行了一次,如果用户在等待列队的过程中关闭了页面,则他的列队信息将保留在数据表中,导致后面的用户永远无法执行操作。于是我们需要改进JS,让他实现每隔一段时间发送一次当前状态。而PHP需要加入判断并删除用户已经离开的信息。
改进工作先从JS下手。
JS复制代码
$('#button').click(function(){
if(confirm("您确定要执行XX") == TRUE)
{
postRequest = setInterval(function(){ //利用setInterval来重复维持用户当前状态
$.ajax({
...
if(queue_info == "its your turn")
{
clearInterval(postRequest); //如果用户开始执行请求,那么就不用再陆续发送状态了,用clearInterval来停止
}
...
});
}, 2000);
}
});
复制代码
接下来,改进PHP文件
PHP复制代码
...
function queue ()
{
//由于JS是随便一个人都能看到的。为了防止有人恶意刷新列队处理页面,我们可以用一些措施来防范。比如referrer来判断用户是否是从某一页面访问的列队处理页面。
$this->load->library('user_agent');
if($this->agent->referrer() == '...'){
$current = date('U');
$expire = $current - 5; //假定我们认为5秒未受到某一个用户的活动信息,就杀掉该ROW
$this->db->where("lastActivity < {$expire}");
$this->db->delete();
...
}
}
...
复制代码
以上就大致架构出用户列队执行的效果。当然本文的还是以方法和方式为重点。与其给出全部代码,不如把整个设计过程阐述清晰,(授人以鱼,不如授人以渔)。大家要是有什么更好的方法或者改进,还请多多发言 |
评分
-
查看全部评分
|