1、轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。
优点:后端程序编写较为容易。
缺点:请求中有大半是无用,浪费带宽和服务器资源。
2、长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资源小。在即时通讯工具中,实时性高。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
3、长连接:在页面里嵌入一个隐蔵iframe,将这个隐蔵iframe的src属性设为对一个长连接的请求或是采用xhr请求,服务器端就能源源不断地往客户端输入数据。
优点:消息即时到达,不发无用请求;管理起来也相对方便。
缺点:服务器维护一个长连接会增加开销。
4、webSocket:前端和服务器只需要一次HTTP握手,整个通讯过程就是建立在一次连接状态中。
优点:一个Web客户端只建立一个TCP连接;Websocket服务端可以推送(push)数据到web客户端;有更加轻量级的头,减少数据传送量;通过协议promote的方式将http升级成websocket。
缺点:不兼容低版本的IE。
即将上线的产品在测试时候,一切都挺好的,等着下班。
产品:查一年的数据出现了连接超时问题,赶紧处理下
开发:...可以,用webSocket这个就行了,再找一个封装好的框架(小意思啦)
产品:我希望今天就解决好问题
开发:...(不可描述的语言)
... ...
开发:还好我之前用过webSocket (https://mp.weixin.qq.com/s/JozHypUdCIwe2MsOhI3fTQ)
... ...
开发:what? 服务器不支持webSocket......(想掀桌的感觉)
开发:哎,还是改用长轮询吧
前端不断请求后台,直到成功获取数据,轮询结束
var params = {
key: '', //作为通过redis中获取值的标识
deptId: 't3o2o323o1dak21';
}
function demo(params){
$.ajax({
type: "post", //AJAX请求类型
url: context.path + "web/myDemo", //请求url
cache: false, //无缓存
timeout: 1000 * 300, //AJAX请求超时时间为30秒
data: params,
success: function(result) {
if(result.key != null){
var param = {
key: result.key
}
demo(param) //调用自身接口请求后台
}
if (result.code=0 && result.key==null) { //成功条件 : result.code=0且 result.key为null
layer.alert("获取数据成功");
console.log(result);
}
if(result.code=-1){ //失败条件 : result.code=-1
layer.alert("请求数据失败");
}
},
error:function(result){
console.log(result);
}
});
}
(1)服务器接收到请求后,无论有没有数据,先返回响应信息给前端,前端界面显示“信息在刷新,请等待下“。
(2)后台的线程处理数据,并把返回的响应数据保存在redis中。
(3)浏览器受到http响应后,立刻发送一个同样的http请求,这次直接在redis中查询是否有数据,当获取数据成功则轮询结束。
@RequestMapping("web/myDemo") public void myDemo(String key, String deptId, HttpSession session, HttpServletResponse response) throws Exception{ Mapresult = new HashMap (); if (StringUtil.isEmpty(key)) { key = ShortUUID.randomShortUUID(); new Thread(new Runnable() { //开启线程,把数据保存在redis中 @Override public void run() { Map result = deptServer.findByDeptId(deptId); redisService.set(key, 150, JSONObject.toJSONString(result)); //对象以json字符串的格式存放在redis中 } }).start(); }else{ String value = redisService.get(key); //直接在redis中获取数据,如果为空是线程还没运行完 if(!StringUtil.isEmpty(value)) { return Response.ok(value).build(); //轮询结束 } } result.put("key", key); result.put("code", 0); ResponseUtil.write(response, result); //无论结果如何,先正常返回数据让前端等待结果(前端显示数据在刷新中) }
待优化......