HTTP协议

HTTP协议大家都很熟悉了,开始本文之前,首先简单回顾一下HTTP协议。

HTTP协议是建立在TCP协议上的应用层协议,协议的本质是请求----应答:

即对于HTTP协议来说,服务端给一次响应后整个请求就结束了,这是HTTP请求最大的特点,也是由于这个特点,HTTP请求无法做到的是服务端向客户端主动推送数据。

但由于HTTP协议的广泛应用,很多时候确实又想使用HTTP协议去实现实时的数据获取,这种时候应当怎么办呢?下面首先介绍几种基于HTTP协议的实时数据获取方法。

短轮询

轮询是最普遍的基于HTTP协议获取实时数据的方式,轮询又分为短轮询和长轮询。短轮询非常简单,用一张图表示一下:

客户端向服务端请求数据,服务端立即将数据返回给客户端,客户端没有拿到想要的数据(比如返回结果告诉客户端,数据处理中),客户端继续发请求,服务端继续立即响应,周而复始。

这种实时数据获取的方式比较粗暴,优点在于编程简单,客户端发请求,服务端实时回响应即可。缺点主要有两个:

  • 无效请求多,每一次无效请求都在浪费带宽和服务器的计算资源
  • 对服务器压力大,定时发请求,并发一高,可能服务端瞬间会收到成千上万个请求,很容易拖垮服务器甚至导致宕机

那么短轮询适合哪种使用场景呢,按照我的理解如果数据变化比较频繁或者能预期到数据在短时间内会发生一次变化的场景可以使用短轮询,比如:

用户在PC端买了一个东西唤起网页端,由于PC端和网页端是不通的,我们预期到用户应该很快会完成付款,这种时候为了开发简单短轮询是一种可以使用的方式,直接服务端提供一个接口告诉客户端订单状态,客户端每5秒请求一次即可,拿到结果就可以不用请求了。

使用短轮询注意要做好请求次数上限的控制,比如请求100次还没检测到用户付款,可以弹窗"请完成付款后去我的订单页面查询"就可以不用请求了。

长轮询

长轮询是另一种实时获取数据的方式,看一下流程:

本质上没有改变,依然是客户端在没有收到自己想要数据的情况下不断发送请求给服务端,差别在于服务端收到请求不再直接给响应,而是将请求挂起,自己去定时判断数据的变化,有变化就立马返回给客户端,没有就等到超时为止。

可以很明显的看到,长轮询的优点就是客户端的请求少了很多避免了无谓的客户端请求,缺点则是服务端会挂起大量请求增加资源消耗且服务器对HTTP请求并发数量是有限制的。

微信网页版的登陆是一个典型的长轮询的例子:

从图上看,客户端不断发送请求到服务器,服务器第一时间并没有给出回应,于是客户端等待,在超时的情况下继续发送请求。

总的来说我理解一般使用长轮询会更多一点,短轮询更加看重的是编程简单,适合小型应用。像微信网页端登录这种,成千上万个用户同时登陆,隔一段时间服务端收成千上个请求去处理哪里受得了,堆机器分摊每台服务器上处理请求的数量终究不是解决问题的办法。

WebSocket

上面介绍了两种轮询方式,但是两种综合起来都有比较明显的缺点,总结起来有以下几个:

  • 伪实时,即上述两种方式都不是真正的实时,无论短轮询的客户端轮询时间多短,还是长轮询的服务端轮询时间多短,都存在一定程度的延时
  • 所有的轮询只要没有需要的数据返回,都是对计算资源的一种浪费
  • HTTP协议本身是一个重的协议,每一次都必须带有HTTP首部+HTTP头部,实际上对我们来说需要的只是HTTP Body而已,多余的数据都是对带宽的一种浪费

因此,最好我们可以做到的事情是:客户端和服务端之间有一条通路,当服务端数据有变化的时候,服务端可以主动推送到客户端。WebSocket就是HTML5之后为了做到这一点而诞生的一种协议,虽然这是一种新的协议,但也是基于HTTP协议的。

看一下WebSocket的原理,很简单:

WebSocket客户端首先通过HTTP协议发送几个特别的header到服务端,告诉服务端现在我发起的是HTTP请求,但我要升级到WebSocket了:

  • Upgrade:websocket
  • Connection:Upgrade
  • Sec-WebSocket-Key: XXX
  • Sec-WebSocket-Protocol: chat, superchat
  • Sec-WebSocket-Version: XX

只要服务器支持WebSocket协议(Tomcat7、Jetty7之后都是支持WebSocket的),那么服务端收到请求且建立连接成功后会返回Sec-WebSocket-Accept、Sec-WebSocket-Protocol这两个header给客户端,且Http Status为101表示协议切换成功,这样客户端和服务端只要任意一方没有断开连接,就可以基于这一条通路进行通讯了。

再谈一下之前提的WebSocket相比长短轮询对于带宽资源的节省。有一个测试,假设HTTP Header是871字节,WebSocket由于数据传输是基于帧的,帧传输更加高效,对比长短轮询,2个字节即可代替871个字节的Header,测试结果为:

相同的每秒客户端轮询的次数,当次数高达10W/s的高频率次数的时候,轮询需要消耗665Mbps,而WebSocket仅仅只花费了1.526Mbps,将近435倍。

WebSocket做到了真正的实时且大量节省带宽资源,但是我理解也有自己的问题,就是开发成本比较高,这里的开发成本倒不是说自己去实现WebSocket,这个在Java语言层面上直接使用Netty-Socketio即可,API很简单,提供了对WebSocket完整的实现,真正的开发成本在于分布式环境下的数据同步问题。

举个例子,有一个在线聊天系统10W人同时在线,此时有一个用户发了一条1K的语音消息,单机保持10W的连接倒是可以(这里不是HTTP请求,因此不受连接池数影响),问题在于带宽。单机同时向10W用户推送1K语音消息,需要的带宽至少10M,这还只是纯粹推送数据出去,没有考虑到数据进来的场景,实际运行过程中需要的带宽会更多,对于企业来说这是一笔非常大的成本。

因此,大量连接的场景下都会做集群(实际就算没有大量连接,为了高可用性,也会做集群),10W并发分出5台机器,平均每台机器有2W连接,考虑集群下会出现的问题:

客户端1把数据发送到服务器1,服务器1连接的所有客户端都可以推送该条语音,但是问题在于:

  • 服务器2~服务器5连的所有客户端如何拿到数据?简单的一种方式是使用消息队列,将数据通过消息队列发送到所有订阅的服务器上
  • 那如果传输的是一张1M的图片,数据太大不适合使用消息队列怎么办,可以先将数据存储下来,消息队列只发送id,收到消息的服务器再根据id去取真正的数据并推送
  • 如果依赖消息队列,那么不仅仅需要对应用进行代码开发,还需要对消息服务器做分布式集群、做压力测试,保证高可用
  • 2W连接正常预计发送1K的消息是没问题的,但是万一用户发送了1M图片导致远超预估带宽怎么办,是业务上取舍不能发送超过XXX的数据还是技术上处理

其他太多需要考虑的问题没有列出来,总而言之,用WebSocket在大量请求、高并发的场景下,代码开发成本是非常高的。但是由于WebSocket可以做到真正的实时服务端对客户端的数据推送且对带宽资源有大量的节省,因此很多IM、音视频、弹幕等应用都会使用WebSocket。

转:

www.cnblogs.com/xrq730/p/9280404.html

基于 HTTP 协议的几种实时数据获取技术(转)的更多相关文章

  1. 基于HTTP协议的几种实时数据获取技术

    原文链接https://www.cnblogs.com/xrq730/p/9280404.html,作者博客园----五月的仓颉,转载请注明出处,谢谢 HTTP协议 HTTP协议大家都很熟悉了,开始本 ...

  2. 基于HTTP协议之WEB消息实时推送技术原理及实现

    很早就想写一些关于网页消息实时推送技术方面的文章,但是由于最近实在忙,没有时间去写文章.本文主要讲解基于 HTTP1.1 协议的 WEB 推送的技术原理及实现.本人曾经在工作的时候也有做过一些用到网页 ...

  3. redixdb 基于redis 协议的实时key-value 存储

    redixdb 是一个基于redis 协议搞的一个实时key value 处理的轻量级应用,支持多种后端 存储模型. 以下是一个小版的容器镜像(官方的太大了) dockerfile   FROM go ...

  4. 一种基于PTP 协议的局域网高精度时钟同步方法(转)

    原文地址 http://www.dzsc.com/data/html/2011-1-17/88338.html 1 引言 在分布式系统中, 常常需要一个全局时间, 用来确定系统中各种事件发生的先后.协 ...

  5. 基于XMPP协议的Android即时通信系

    以前做过一个基于XMPP协议的聊天社交软件,总结了一下.发出来. 设计基于开源的XMPP即时通信协议,采用C/S体系结构,通过GPRS无线网络用TCP协议连接到服务器,以架设开源的Openfn'e服务 ...

  6. 基于XMPP协议的手机多方多端即时通讯方案

    一.开发背景 1.国际背景 随着Internet技术的高速发展,即时通信已经成为一种广泛使用的通信方式.1996年Mirabilis公司推出了世界上第一个即时通信系统ICQ,不到10年间,即时通信(I ...

  7. 通信——基于Xmpp协议实现的聊天室

    前段时间写了个自定义通信协议的聊天室(即用\r\n标记字符串,作为一句话),总感觉自己弄的那个协议实现虽然简单,但是拓展性就太差了,只适合于发送聊天的内容,难以包含更多的信息.基于上述几点,于是就开始 ...

  8. 基于FPGA的线阵CCD实时图像采集系统

    基于FPGA的线阵CCD实时图像采集系统 2015年微型机与应用第13期 作者:章金敏,张 菁,陈梦苇2016/2/8 20:52:00 关键词: 实时采集 电荷耦合器件 现场可编程逻辑器件 信号处理 ...

  9. springboot+websocket+sockjs进行消息推送【基于STOMP协议】

    springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...

随机推荐

  1. vue.js移动端app实战1

    本系列将会用vue.js2制作一个移动端的webapp单页面,页面不多,大概在7,8个左右,不过麻雀虽小,五脏俱全,常用的效果如轮播图,下拉刷新,上拉加载,图片懒加载都会用到.css方面也会有一些描述 ...

  2. MySQL备份工具收集

    说明:MySQL的备份不像SQL Server那么的简单,备份时需要分数据库引擎类型,现在主流的就两个:InnoDB和MyISAM,而这两种类型备份方式各不一样. MyISAM: mysqlhotco ...

  3. java.io.IOException: Cannot run program "java" (in directory "/data01/var/lib/jenkins/workspace/2540cb62a866eda983ab8cba34fcd4f9"): error=2, No such file or directory

    通过下图所示方式,可以在同一台机器上启动多个jenkins slave 执行项目的时候报错: 解决办法:首先排查,目标文件或者目录是否存在,如果存在,则在目录机器添加/usr/bin/java的软链接 ...

  4. z pre-pass 相关问题的讨论

    z pre-pass 是指在渲染流程中,第一个pass先画一张深度buffer出来,得到需要绘制的最前面这层深度,用这个在接下来的pass中做深度剔出,这样在第二个pass中会省略很多绘制. 这项技术 ...

  5. Hadoop一些问题总结

    1.运行mr程序出错 connecting to resoucemanager retrying .... retrying ..... 原因是没有启动yarn或者启动失败 2.初始化工作目录结构 h ...

  6. Win7如何解决内存不能为Read的批处理命令

    将下面文件保存为"解决内存不能为Read的批处理命令.cmd"双击运行即可   for %%1 in (%WinDir%\system32\*.dll) do regsvr32.e ...

  7. vector(可变数组) 用于UDP通信

    头文件: #include<vector.h> 然后,声明并初始化vctor数组. vector<char>  str(len); 其中len可以是变量或者常量.(其实用常量就 ...

  8. RelativeLayout布局(仅在RelativeLayout中有效)

    在父亲布局的相对位置 android:layout_alignParentLeft="true"     //在布局左边 android:layout_alignParentRig ...

  9. Oracle 字段类型

    Oracle 字段类型 http://www.cnblogs.com/lihan/archive/2010/01/06/1640547.html 字段类型 描述 字段长度及其缺省值 CHAR (siz ...

  10. Android VS IOS

    时间: IOS:var d = new Date("2018-04-19 14:23:00".replace(/-/g, "/")); (d = new Dat ...