websocket VS 轮询htpp请求
首先为什么会出现这两种情况的比较呢。
最近公司在一个APP项目中出现了一个问题,就是当APP后台管理审批同意后APP没有得到及时的更新,需要重新登录才能更新。
这时候我们前后端一起讨论解决方案,大家都提出的是websocket
的解决方案,但是websocket
会存在以下问题。
-
websocket的问题:
- 第一个问题就是麻烦,由于我们的后端架构是微服务的架构,并且使用了
redis
缓存,如果使用websocket
那么我们将为这一个小功能耗费大量的时间。
麻烦在哪? 首先由于是微服务架构多台机器,所以需要将建立连接的
socket
存入缓存,不然不知道是哪台机器建立了连接。其次就是需要写心跳,保持连接,避免断开等的情况。
+ 第二个问题就是兼容性,由于我们这个项目可能需要做web端,那么肯定存在兼容性问题,当然很多情况都可以不去考虑兼容性问题。可以使用scokjs.js
- 第一个问题就是麻烦,由于我们的后端架构是微服务的架构,并且使用了
-
websocket的优点:
- 性能消耗小,通信非常高效,由于是tcp连接基本是不断的,来回发送消息效率开销会小很多不用每次都建立连接。
- 相对于web端来讲没有同源限制。
-
轮询http请求
- 这里有两种方式
- 第一种是轮询每隔一段时间向服务器发送请求
- 第二种是长轮询,建立连接后一直持续在等待响应的过程中,直到超时或者接收到响应后再重新建立连接,这个是阻塞的。
- 他们的缺点:
- 性能开销大,每次都要重新发起新的请求
- 第一种轮询需要后台有一定的处理强度,用户多起来的时候,请求会非常的多。
- 第二种长轮询需要后台有一定的并发处理能力,同样用户一多,阻塞的请求将会非常之多。
- 他们有没有优点呢?(看场景)
- 第一兼容性好。
-
第二好实现,不麻烦。我知道,当我写出这句话肯定很多人会反对,你个程序员这点事情还怕麻烦.....可是你想想我们这个功能真的是一个非常小的功能。有句话说的好"杀鸡焉用牛刀",就是这个道理。
- 这里有两种方式
所以我们的项目中用了阻塞式http,也就是长轮询。
最后放上java
的实现代码(同事的),看了一下感觉不错。
public static final Map<String, Thread> threadMap = new ConcurrentHashMap<>();
public static final Map<String, Boolean> haveUpdateMap = new ConcurrentHashMap<>();
public void haveUpdate(HttpServletRequest request, HttpServletResponse response, String cellphone, String mac) {
if(threadMap.get(cellphone) == null){
// 第一次调用
threadMap.put(cellphone, Thread.currentThread());
LockSupport.park();
}else{
Thread thread = threadMap.get(cellphone);
LockSupport.unpark(thread);
threadMap.put(cellphone, Thread.currentThread());
LockSupport.park();
}
Boolean haveUpdate = haveUpdateMap.get(cellphone);
if(haveUpdate != null){
// 已更新
haveUpdateMap.remove(cellphone);
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
try {
Result success = Result.success("success");
writer = response.getWriter();
String s = JSON.toJSONString(success);
writer.print(s);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null){
writer.close();
}
}
}else{
System.out.println("=========offer=================");
return;
}
}