服务器推送的实现—基于EventSource

摘要:
1.1服务器推送的目的是及时推送客户端感兴趣的数据。短的数据轮询间隔将对服务器造成更大的压力。1.4使用服务器推送的限制是什么?当然,每个客户端都需要保持长连接。1.5如果在使用服务器推送的场景中满足以下条件,则要求客户端能够及时感知服务器数据的变化。客户端的数量可以在服务器的承载范围内。2.实现服务器推送的方法很多。
一、服务器推送理解

  首先要知道为什么使用服务器推送,回答这个问题其实就是相当于回答,服务器推送的优点,可以从两个方面来思考:

1.1 服务器推送的目的

  及时的将客户端感兴趣的数据推送给它。

1.2 不是用服务器推送怎么来实现需求

  不使用服务端推送,那就只能由客户端定期对服务器发送请求,来获取是否有需要的数据。这样做有几个缺点:

  • 不能及时的获取,最大延时时间为轮询间隔。
  • 浪费资源,大部分的请求,都不会得到数据
  • 轮询间隔短会对服务器造成较大的压力。

1.3 使用服务器推送可以带来什么好处

  我理解的有两个好处,一是及时,还有就是消耗资源稳定(消耗一个连接数)。及时很好理解,就是服务器知道数据什么时候发生变化,发生变化的时候就进行推送。而消耗资源稳定,则是因为只有一个连接,所有的数据都从这么连接发送。

1.4 使用服务器推送有哪些局限性

  当然就是每一个客户端都需要维护一个长连接,客户端数量增多的时候,会对服务器造成较大的压力。

1.5使用服务器推送的场景

  如果满足以下条件,那么使用它是最好的做法,若不全部满足,则酌情考虑:

  • 要求客户端能及时的感知服务器数据的变化
  • 客户端的数量能在服务器的承受范围内
二、服务器推送的实现

  服务器推送的实现有很多种方式,这一篇博客使用EventSource来实现功能。若要实现服务器推送,需要客户端和服务端同时对其进行支持。

2.1 客户端代码

  客户端代码比较简单,实现一个回调函数即可:

new EventSource("longConnection").onmessage = function(event) {
    $scope.$apply(function() {    
        alert(event.data);        
    }); 
};

  回调函数中的event.data就是服务器发送的数据,此时可以对它进行其它操作。

2.2 服务端代码

  服务端的代码一般放到一个循环中:

response.setContentType("text/event-stream;charset=UTF-8");
response.setHeader("Cache-Control","no-cache");
response.setHeader("Connection","keep-alive");
PrintWriter out=response.getWriter();
while(true){
    out.print("data: " + 传递的数据 + "

");
    out.flush();
}

  只要不把连接关闭,那么每一次刷新,都会讲数据发送到客户端,并触发onmessage方法。

2.3 注意事项

2.3.1 浏览器的支持问题

  默认IE是不支持EventSource对象的,解决办法是引入一个js文件eventsource.min.js,但是也只能支持IE8及以上。

2.3.2 服务器数据问题

  从上面的例子中可以发现,往客户端发送数据的代码是写在一个死循环中,那么怎么才能实现当敏感数据发生变化时,才使其执行呢,可行性办法有很多,现在提供一个方法,在全局范围内使用LinkedBlockingQueue对象,当有需要发送的数据时,将数据放到队列中,然后在循环中调用poll方法即可。

三、EventSource深入理解

  如果细心的话可以发现,在服务端代码中,写数据的使用使用了如下格式:

out.print("data: " + 传递的数据 + "

");
out.flush();

  每次写完刷新可不用说,重点是写数据的时候,有一个前缀和后缀,那么这个是有什么规定吗,还是说与页面js代码一一对应即可,答案是有规定的。下面使用F12对长连接进行观察,可以看到如下内容:

服务器推送的实现—基于EventSource第1张

  具体可以使用哪些前缀,有id,data,event,retry和空白,而后缀使用两个换行,实际上这代表着是一个空行,学习过servlet上传的可能会理解。

  • id:代表本次事件
  • data:表示传递的数据
  • event:代表触发的事件
  • retry:代表断开重连后再次等待的时间

  一般用法都是在传递的数据中使用json,里面存放需要调用的方法名,调用参数放在后面,这样就可以根据不同的数据类型进行不同的处理。

  同样的客户端代码中使用了onmessage方法,那么是否只有这一个方法呢,其实还有额外的两个方法,这两个方法视情况使用 :

  • onopen:这个是在连接成功后触发的。
  • onerror:这个是在出现异常的时候出发的。
四、总结

  这个只是服务端推送的一种实现方式,基本能满足要求,还有其他方式,后面会介绍。

免责声明:文章转载自《服务器推送的实现—基于EventSource》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇OpenCV+QT开发环境(一):Windows环境电商实例、业务并发、网站并发及解决方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

XNA框架基础——XNA介绍

第1章:XNA介绍 欢迎来到XNA的世界。作为一个游戏程序员,你或许知道 DirectX ,甚至也许具有XNA 框架的基础知识。 这一个章节解释了如何安装 XNA Game Studio Express 和如何以有效率的方式使用它。它也包含相当多的技巧,这些技巧甚至可能对任何一个已经知道基础知识的人都有用。 在下面一些章节中,你将直接地开始开发一些很酷的...

第三方软件 Serv-u提权

Serv-U FTP Server,是一种被广泛运用的FTP服务器端软件,支持3x/9x/ME/NT/2K等全Windows系列。可以设定多个FTP服务器、限定登录用户的权限、登录主目录及空间大小等   Serv-U提权分两种 1.有修改权限 2.无权限修改 第一种情况时 0.判断是否安装serv-u serv-u的默认端口是43958  可以用nmap...

Hive操作(集合操作,删除表操作)

(一)集合数据类型 数据类型 描述 语法示例 STRUCT 和c语言中的struct类似,都可以通过“点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT{first STRING, last STRING},那么第1个元素可以通过字段.first来引用。 struct() MAP MAP是一组键-值对元组集合,使用数组表示法可以访问...

根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax

基本介绍 XmlHttpRequest XmlHttpRequest是JavaScript中原生的,历史悠久的一种发送网络请求的方案。 基本上所有前端框架对于网络请求的部分都是基于它来完成的。 在本章节中我们将了解它的基本用法,并且会实现一个与jQuery.ajax功能百分之九十相似的网络请求组件。 我是没有读过jQuery.ajax源码的,并且我也不是一...

CDI services--interceptors(拦截器)

1.拦截器综述 拦截器的功能是定义在Java拦截器规范。 拦截器规范定义了三种拦截点:  业务方法拦截, 生命周期回调侦听, 超时拦截(EJB)方法。 在容器的生命周期中进行拦截  public class DependencyInjectionInterceptor { @PostConstruct public void inject...

Ant Design Pro V5 从服务器请求菜单(typescript版)

【前言】 找了很多Admin模板,最后还是看中了AntDesignPro(下文简写antd pro)这个阿里巴巴开源的Admin框架,长这样(还行吧,目前挺主流的): 官网地址:https://pro.ant.design/index-cn 该套模板是使用了React开发框架作为基础,AntDesign(蚂蚁金服开源UI组件库)作为UI库,集成了Dva,...