背景介绍

由于近期压测平台的开发,期中设计到的一个功能点就是要实时监控任务的运行状态一旦改变要及时在页面更新状态,首先压测用例的运行状态是保存在服务端那么客户端如何做到实时监控呢?初步想来无非两种式:

  1. 服务端主动推数据
  2. 客户端每隔一段时间主动拉数据 ### 服务端主动推数据 这种方式主要是给予 HTTP 的长连接的 ‘服务器推’ 技术,能使服务器主动异步的方式向客户端推数据,我研究过以下的实现方式

代码实现

@app.route("/getRunStatus",methods = [ "POST", "GET" ] )
def get_run_status():
    try:
        #服务端每隔3s返回一次数据,此时线程一直是挂起状态直到有结果数据返回给客户端
        while 1:
            rid =request.form.get( "id", "")
            time.sleep(3)
            #获取客户端需要返回的信息
            results = RelayPressCaseSql().select_press_cases_by_sid(rid)
            if results.run_status == 2 or  results.run_status==3 or results.run_status==1:
                 return jsonify(msg="success",rstatus=results.run_status)
    except Exception as e:
        return jsonify(msg="get_run_status fail")
        logger.exception('get_run_status fail')

前端代码

//前端ajax 请求
function setTimePostInfo(){
    $.ajax({
          url : "/getRunStatus",
          type : "post",
          dataType : "json",
          data: {
              id:rid
          },
          success : function(data) {
                var resData = data.rstatus
                //一旦服务端有响应数据,此时模拟处理客户端逻辑
                alertresData 
            },
            error:function(data){
                alertmsg(data.msg);
                console.log(data.msg);
            }
        });
}

遇到的问题
此种方式我在项目中遇到的弊端就是在同一个 Html 页面中发起一个长轮询请求后服务端会挂起当前线程,此时客户端一直处于等待响应阶段,由于 html 刷新机制是单线程,所以就会影响同一个 html 页面中的其他请求都会被挂起如图所示

客户端定时拉数据

  1. 所谓的 Ajax 轮询,其实就是定时的通过 Ajax 查询服务端,客户端按规定时间定时像服务端发送 ajax 请求,服务器接到请求后马上返回响应信息并关闭连接。这种技术方式实现起来非常简单,但是这种方式会有非常严重的问题,就是需要不断的向服务器发送消息询问,这种方式会对服务器造成极大的性能浪费。
  2. 还有一个类似的轮询是使用 JSONP 跨域请求的方式轮询,在实现起来有差别,但基本原理都是相同的,都是客户端不断的向服务器发起请求。
  3. 优点 实现简单。
  4. 缺点 这是通过模拟服务器发起的通信,不是实时通信,不顾及应用的状态改变而盲目检查更新,导致服务器资源的浪费,且会加重网络负载,拖累服务器。
  5. 但是 简单看似没有什么优点的东西,存在即是合理,就像 TCP 和 UDP 俩哥俩一样你能说 UDP 是没用的嘛?答案是否定的,所以基于我项目情况虑,有以下几点,我选择这种方式:
  6. 实现模型
  7. 代码实现

    @app.route("/getRunStatus",methods = [ "POST", "GET" ] )
    def get_run_status():
    try:
        #服务端每隔3s返回一次数据
    
      rid =request.form.get( "id", "")
      time.sleep(3)
      #获取客户端需要返回的信息
      results = RelayPressCaseSql().select_press_cases_by_sid(rid)
      if results.run_status == 2 or  results.run_status==3 or results.run_status==1:
        return jsonify(msg="success",rstatus=results.run_status)
    except Exception as e:
        return jsonify(msg="get_run_status fail")
        logger.exception('get_run_status fail')
    

    前端代码

    //前端ajax 请求
    function setTimePostInfo(){
    $.ajax({
          url : "/getRunStatus",
          type : "post",
          dataType : "json",
          data: {
              id:rid
          },
          success : function(data) {
                var resData = data.rstatus
                //一旦服务端有响应数据,此时模拟处理客户端逻辑
                if (resData ==1){
                      //模拟轮询处理结束逻辑
                    }else{
                        //递归实现客户端定时轮询
                        setTimeout(function(){ setTimePostInfo(); }, 8000);
                    }
            },
            error:function(data){
                alertmsg(data.msg);
                console.log(data.msg);
            }
        });
    }
    

    总结

    其实还有很多其他的实现方式,下面只做一个方向总结,具体问题还是要具体分析,具体技术选择,如下:

博主信息

签名:一个喜欢阿伦艾弗森的测试开发工程师
QQ:294040201
喜欢就点个赞,转个发,关个注吧~
博主博客:http://blog.csdn.net/a11en_03


↙↙↙阅读原文可查看相关链接,并与作者交流