实现一个简单的服务端推送方案-实例篇Polling(服务端阻塞读)

前面讲过一篇《实现一个简单的服务端推方案-实例篇Polling》,那篇文章服务端的实现是不停的轮循数据库,这篇将服务器端轮循数据库改为服阻塞的方式读取队列,减轻数据库服务器的压力。


客户端代码,JS库为prototype.js

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<script language="JavaScript" type="text/javascript" src="./prototype.js"></script>
</head>
<body>
<script language="JavaScript">
  var Class = {
    create: function() {
      return function() {
        this.initialize.apply(this, arguments);
      }
    }
  }
  var Comet = Class.create();
  Comet.prototype = {
      maxvid: 0,
      url: './backend.php',
      noerror: true,
      initialize: function(){
      },
      connect: function(){
          this.ajax = new Ajax.Request(this.url, {
              method: 'get',
              parameters: {
                  'maxvid': this.maxvid
              },
              onSuccess: function(transport){
                  var response = transport.responseText.evalJSON();
                  this.comet.maxvid = response['vid'];
                  this.comet.handleResponse(response);
                  this.comet.noerror = true;
              },
              onComplete: function(transport){
                  if (!this.comet.noerror) setTimeout(function(){
                                           comet.connect()
                                           }, 5000);
                  else
                  this.comet.connect();
                  this.comet.noerror = false;
              }
          });
          this.ajax.comet = this;
      },
      handleResponse: function(response){
          $('content').innerHTML += '<div>'
                                 + response['vid']    + ','
                                 + response['doorno'] + ','
                                 + response['rfsim']  + ','
                                 + response['optime'] + ','
                                 + response['ynopen']
                                 + '</div>';
      }
  }
  var comet = new Comet();
  comet.connect();
</script>
<div id="content"></div>
</body>
</html>

服务器端PHP代码,backend.php,队列使用gearman

<?php

ignore_user_abort(true);

header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
ob_flush();
flush();
//控制浏览器前端不要缓存结果,每次都要重新查询

$maxvid = $_GET["maxvid"];
error_log(date("[Y-m-d H:i:s]")." > "."maxvid: ".$maxvid."\n", 3 , "/usr/local/apache2219/logs/php_log");

$gmworker = new GearmanWorker();
$gmworker->setTimeout(60000);
$gmworker->addServer();
$gmworker->addFunction("getmsg", "getmsg");

if ( ($gmworker->work()) && ($gmworker->returnCode() == GEARMAN_SUCCESS) )
{
  echo $msg;
  ob_flush();  //必须有,不然是在PHP_BUFFER不会被发送到客户端
  flush();
  if ( connection_status() ) {
    error_log(date("[Y-m-d H:i:s]")." < ".$msg.",but connection aborted!\n", 3 , "/usr/local/apache2219/logs/php_log");
  } else {
    error_log(date("[Y-m-d H:i:s]")." < ".$msg."\n", 3 , "/usr/local/apache2219/logs/php_log");
  }
  //由于服务端阻塞读队列,无法感知客户端是否断开
  //所以当客户端中断后,后台PHP仍在阻塞读,这时如果队列有新的消息便会被读出但又无法送达前端,导致消息丢失
  //所以这里只能在发送后判断客户端连接状态,做特殊判断处理
}

function getmsg($job)
{
  global $msg;

  $msg = $job->workload();

  $result = "OK";

  return $result;
}

?>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值