接近年关了,最近一直在准备年终汇报的PPT,顺便在做一个《高并发网络程序设计》的PPT,我联想到《计算机组成原理》中的外设管理的中断和轮循方法,想把socket比作成外设,当然这里socket是非阻塞的,事件都是异步的。又想着将这个类比推广到互联网架构中,数据同步的方法:poll和push。
poll方式 poll方式,也称为轮循,是大家都比较熟悉的一种数据同步方式,客户端定期去ping查询服务器,确定是否有需要的数据。例如,软件更新模块,客户端软件需要定期去查询官方网站,判断当前是否有更新的版本,如果有就提醒用户进行升级。邮件客户端,需要定期查询邮件服务器,查询是否有新的邮件。RSS阅读器,也是需要不断的查询rss地址的状态,如果有更新,就将数据拿回来。
当服务器没有数据的时候,poll方式会
浪费大量的带宽 。
为了降低带宽,通常是采用减低poll的频率来实现的,这就导致了消息的长延迟,实时性不高。像gmail的POP3邮件检查间隔从10分钟到1小时不等。
push方式 poll的问题在于很多情况下,通信信道是单向的。为了解决poll的问题,可以
将通信信道设计为双向的 ,这样就可以服务器采用push的方式主动向客户端进行数据同步了。双向通信信道设计,考虑到要穿透NAT和防火墙,很多实现采用长连接。例如各种IM的实现:MSN是TCP的长连接,QQ是UDP模仿的长连接,GTALK是HTTP模仿的长链接。
push方式,服务器主动向客户端推送数据。当前实现push方式有两种方法:
1. 客户端首先连接到服务器,并维持长连接
2. 服务器能够直接访问到客户端,不需要长连接
在国内NAT和firewall遍地都是的情况下,第2种方法不是很可行,但是对于一些企业应用,这种方法还是不错的,比如后面提到的pubsubhubbub。
但是push方式,通常需要长连接,对于服务器端其实也是一个不小的压力,虽然现在C10K问题得到了比较好的解决,但是对于一些大规模互联网应用来讲,用户数是数以亿计的,单单是维持TCP连接,就需要太多的服务器。因此,除了一些
实时性要求比较高的应用 ,现在push方式使用的范围还不是很广,例如push方式在IM、服务器监控等领域都有应用。
下面选取这两天看的两个东东,来理解一下poll和Push。
XMPP xmpp类似于email系统,将一个消息从一个JID送达到另一个JID。xmpp通常被用作im,那么它是如何实现实时消息传送的呢。我们接下来讨论的BOSH技术就是解决这个问题的。BOSH也就是Bidirectional-streams Over Synchronous HTTP,在HTTP上模拟长连接,gtalk就是用的这种方法。
BOSH 技术能够同时减小网络带宽和减小客户端响应的时间。其方案是对客户端的请求连接管理器不给于返回直到数据已经就绪,当客户端收取连接管理器返回的数据会向连接管理器发送下一个请求,于是连接管理器总是保持着一个客户端的请求,当服务器端数据就绪的时候,可以将数据封装在请求的响应包中,“推送”给客户端。
如果双向连接长时间没有数据,连接管理器负责给客户端发送一个空包,空包触发客户端发送新的请求,连接管理器通过这种机制判断连接是否已经中断,由于 BOSH 不是轮询的机制,带宽消耗比标准的 TCP 连接大不了多少。
由于大多数的客户端不支持 HTTP 的 Pipeling (单一的连接上承载并发的请求),于是,客户端必须从第二条 HTTP 连接发送消息。当第二条 HTTP 连接有新的请求发送的时候,连接管理器将第一条连接中的请求返回,即便此时第一条连接中的返回的是空数据包。这样做的原因是让客户端有需要的话可以发送新的请求过来。客户段同一时间最多只能保持两条 HTTP 连接,否则的话,客户端必须等待旧的请求处理完之后才能发送新的请求
在网络经常中断的环境下, BOSH 退化成每个数据请求一个新 HTTP 连接。然而,在通常情况下,网络环境良好,客户端可以使用 http/1.1, 这个时候,一个 Session 包含两个 TCP 长连接,所有的请求都在这两个长连接上传输。基本上任何时候,客户端通过一条连接能够推送数据到服务器,与此同时,服务器端可以“推送”数据到客户端。值得注意的是,这两条长连接的角色在客户端每发送一次请求则角色转换一次。
尽管大多数时间可以随时推送数据到对端,但是,如果一方刚刚推送完数据,则需要等一个网络来回的时间才能推送下一个数据。
pubsubhubbub pubsubhubbub是Google的工程师开发的一种协议,可以在ATOM和RSS更新的时候,订阅者能实时得到更新,实现一种基于RSS Feed的类似Twitter的实时效果。
PubSubHubbub 协议在供稿网址内容更新后,能接近即时的得到通知(通过webhook回调)。sub(订阅者)向要订阅的RSS中指定的hub进行注册,hub和pub(发布者)之间通过poll和push等方式同步数据,然后hub向已经注册的sub推送更新后的数据。
这样,就能够实时的得到RSS的更新,而且避免了sub不断轮循pub,节省了带宽。但是,这有一个缺点,就是hub向sub推送消息,就回到最初我们讨论的两种方法,现在pubsubhubbub中sub大都要求为公网可访问,但是对于一些企业应用,像google reader,这样做还是会节省很大带宽的。
PubSubHubbub 协议概述如下:
1. 一个供稿网址( “主题” )通过 标签在其Atom或RSS的XML文件中声明其Hub server (枢纽服务器) 。这个 Hub(s) 可以由feed的发布者运行,也可以是一个任何人都可以使用得社区 Hub (community hub)。
2. 一个订阅者(对某个主题有兴趣的服务器) ,首先正常的抓取Atom网址。如果Atom档案声明它是 Hub ,订阅者就可以避免重复查看网址,而是在feed的 Hub 注册和订阅更新。
3. 订阅者通过主题的URL的声明的 Hub 订阅这个主题。
4. 当作者更新主题时,Hub 被告知发生了一个更新。
5. 之后 Hub 有效提取 feed 然后同时将新更改后的内容广播向所有订阅的用户。
详细的可以查看参考5中的那个slide。
参考: http://shallon.javaeye.com/blog/126428 http://yblog.org/archive/index.php/8856
阅读(6416) | 评论(0) | 转发(0) |