ajax轮询在压测平台中的应用

来源:互联网 发布:电子相册软件源码 编辑:程序博客网 时间:2024/05/20 17:23

背景介绍

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

服务端主动推数据

这种方式主要是给予HTTP的长连接的‘服务器推’技术,能使服务器主动异步的方式向客户端推数据,我研究过以下的实现方式
- ajax的长轮询(long-polling)方式
1. 服务器端会阻塞请求直到有数据传递或超时才返回。
2. 客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接
3. 当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。
4. 实现模型如图
long-polling
代码实现

@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                //一旦服务端有响应数据,此时模拟处理客户端逻辑                alert(resData )            },            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是没用的嘛?答案是否定的,所以基于我项目情况虑,有以下几点,我选择这种方式:
    • 压测平台压没有并发用户的场景
    • 数据更新时延没有严格要求-,10s的时延我都可以接受,嘿嘿嘿
    • 完美解决了我同一个html页面处理其他请求的需求
    • 每隔10几秒让服务器处理个任务简直就可以忽略不计因为我的施压服务和被压服务都是和策略服务分离的~欧耶~
  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);            }        });}

总结

其实还有很多其他的实现方式,下面只做一个方向总结,具体问题还是要具体分析,具体技术选择,如下:
- websocket方式(WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议)
- Comet的方式
优点: 实时性好(消息延时小);性能好(能支持大量用户)
缺点: 长期占用连接,丧失了无状态高并发的特点。
- 基于 Iframe 及 htmlfile 的流(streaming)方式

博主信息

签名:一个喜欢阿伦艾弗森的测试开发工程师
QQ:294040201
喜欢就点个赞,转个发,关个注吧~

原创粉丝点击