[转] 消息系统该Push/Pull模式分析
信息推拉技术简介
“智能信息推拉(IIPP)技术”是在网上信息获取技术中加入了智能成份,从而有助于用户在海量信息中高效、及时地获取最新信息,提高了信 息系统主动信息服务的能力。如果引入基于IIPP的主动信息服务系统,则可根据用户的特性提供具有针对性的、个性化的信息服务。
以往在Internet上搜寻信息,最常用的方法就是浏览器发出请求后,Web就将信息传送给用户,此过程用户需要“拉取”信息而被描述为 Pull;而将信息直接“推送”到用户的计算机的方法就是信息推送,称之为Push,用户只需要在初次使用时自己设定所需要的信息频道,此后,定制信息将 通过Web自动传给用户。
信息推拉技术智能化
在传统的Client/server结构中,信息获取方式是按“拉”(Pull)的模型进行的:服务器根据用户终端发送的服务请求进行处理 并返回用户所需的结果。在Push系统中,服务器把信息“推”给用户终端系统。虽然两者数据传输的方向都是从服务器流向用户,但操作的发起者是不同的。从 “信源”与“用户”的关系来看,信息的流动可分为两种模式,即信息推送与信息拉取模式。
Push与Pull之比较
推送(Push)技术是根据用户需要,有目的、按时将用户感兴趣的信息主动发送到用户的计算机中。Push技术的主要优点是对用户要求低, 普遍适用于广大公众,不要求有专门的技术;二是及时性好,信源及时地向用户“推送”不断更新的动态信息。但是,在随后实际应用中,因为存在以下几方面不 足,Push技术并没有取得预期的成功:
- 不能确保发送成功。由于Push技术采用广播方式,当网络信息中心发送信息时,只有接收器打开并正好切换到同一频道上,传输才能发生作用,用户才能获取信息。这对于那些要确保能收到信息的应用领域是不太适合的。
- 没有信息状态跟踪。Push技术采用的是“开环控制”模式,一个信息发布以后的状态,如用户是否接收,或客户端收到后是否按信息的提示执行了任务等,这些“反馈信息”发布者无从得知。
- 针对性差。推送的信息内容缺乏针对性,不能满足用户的个性化需求。有价值的重要信息,通常都是要针对一些特定的群组来发送的,即只送给相关的人士。Push技术不能满足上述需求。
- 信源任务重。信源系统要主动地、快速地、不断地将大量信息推送给用户。
拉取(Pull)技术指用户有目的地在网络上主动查询信息,用户从浏览器给Web发出请求,由Web获取所需信息。面对拥有海量信息的 Internet环境,搜索引擎是有效的网络信息“拉取”(查询)的检索工具。Pull技术的主要优点是针对性强,能满足用户的个性化需求;信息传输量 小,网络上所传输的只是用户的请求和服务器针对该请求所作的响应;信源任务轻,信息系统只是被动接受查询,提供用户所需的部分信息。其主要缺点是及时性 差,由于用户只会基于自己的知识水平(或专业水平)提出请求,当信源中信息更新变化时,用户难以及时拉取新的动态信息,虽然可以通过定时查询来解决这个问 题,但是会浪费大量的网络资源和人力,而且,仍不能保证最好的实时性。对用户要求高,要求用户对信源系统有相应的专业知识,掌握相关的检索技术。
PUSH和PULL模型对比
PUSH和PULL两种模式结合
- 将信息推送与拉取两种模式结合能做到取长补短,使二者优势互补。根据推、拉结合顺序及结合方式的差异,又分以下四种不同推拉模式:
- 先推后拉——先由信源及时推送公共信息,再由用户有针对性地拉取个性化信息;
- 先拉后推——根据用户拉取的信息,信源进一步主动提供(推送)与之相关的信息;
- 推中有拉——在信息推送过程中,允许用户随时中断并定格在感兴趣的网页上,以拉取更有针对性的信息;
- 拉中有推——根据用户搜索(即拉取)过程中所用的关键字,信源主动推送相关的最新信息。
Related posts:
- IIS日志配置方案
-
无论是消息系统,还是配置管理中心,甚至存储系统,你都要面临这样一个选择,push模型 or pull模型?是服务端主动给客户端推送数据,还是客户端去服务器拉数据,一张图表对比如下:
push模型 pull模型 描述 服务端主动发送数据给客户端 客户端主动从服务端拉取数据,通常客户端会定时拉取 实时性 较好,收到数据后可立即发送给客户端 一般,取决于pull的间隔时间 服务端状态 需要保存push状态,哪些客户端已经发送成功,哪些发送失败 服务端无状态 客户端状态 无需额外保存状态 需保存当前拉取的信息的状态,以便在故障或者重启的时候恢复 状态保存 集中式,集中在服务端 分布式,分散在各个客户端 负载均衡 服务端统一处理和控制 客户端之间做分配,需要协调机制,如使用zookeeper 其他 服务端需要做流量控制,无法最大化客户端的处理能力。 其次,在客户端故障情况下,无效的push对服务端有一定负载。
客户端的请求可能很多无效或者没有数据可供传输,浪费带宽和服务器处理能力 缺点方案 服务器端的状态存储是个难点,可以将这些状态转移到DB或者key-value存储,来减轻server压力。 针对实时性的问题,可以将push加入进来,push小数据的通知信息,让客户端再来主动pull。 针对无效请求的问题,可以设置逐渐延长间隔时间的策略,以及合理设计协议尽量缩小请求数据包来节省带宽。
在面对大量甚至海量客户端的时候,使用push模型,保存大量的状态信息是个沉重的负担,加上复制N份数据分发的压力,也会使得实时性这唯 一的优点也被放小。使用pull模型,通过将客户端状态保存在客户端,大大减轻了服务器端压力,通过客户端自身做流量控制也更容易,更能发挥客户端的处理 能力,但是需要面对如何在这些客户端之间做协调的难题。
客户端和服务端的交互有推和拉两种方式:如果是客户端拉的话,通常就是Polling;如果是服务端推的话,一般就是Comet,目前比较流行的Comet实现方式是Long Polling。
注:如果不清楚相关名词含义,可以参考:Browser 與 Server 持續同步的作法介紹。
先来看看Polling,它其实就是我们平常所说的轮询,大致如下所示:
Polling
因为服务端不会主动告诉客户端它是否有新数据,所以Polling的实时性较差。虽然可以通过加快轮询频率的方式来缓解这个问题,但相应付出的代价也不小:一来会使负载居高不下,二来也会让带宽捉襟见肘。
再来说说Long Polling,如果使用传统的LAMP技术去实现的话,大致如下所示:
Long Polling
客户端不会频繁的轮询服务端,而是对服务端发起一个长连接,服务端通过轮询数据库来确定是否有新数据,一旦发现新数据便给客户端发出响应,这次交互便结束了。客户端处理好新数据后再重新发起一个长连接,如此周而复始。
在上面这个Long Polling方案里,我们解决了Polling中客户端轮询造成的负载和带宽的问题,但是依然存在服务端轮询,数据库的压力可想而知,此时我们虽然可以通过针对数据库使用主从复制,分片等技术来缓解问题,但那毕竟只是治标不治本。
我们的目标是实现一个简单的服务端推方案,但简单绝对不意味着简陋,轮询数据库是不可以接受的,下面我们来看看如何解决这个问题。在这里我们放弃了传统的LAMP技术,转而使用Nginx与Lua来实现。
Modified Long Polling
此方案的主要思路是这样的:使用Nginx作为服务端,通过Lua协程来创建长连接,一旦数据库里有新数据,它便主动通知Nginx,并把 相应的标识(比如一个自增的整数ID)保存在Nginx共享内存中,接下来,Nginx不会再去轮询数据库,而是改为轮询本地的共享内存,通过比对标识来 判断是否有新消息,如果有便给客户端发出响应。
注:服务端维持大量长连接时内核参数的调整请参考:http长连接200万尝试及调优。
首先,我们简单写一点代码实现轮询(篇幅所限省略了查询数据库的操作):
lua_shared_dict config 1m;
server {
location /push {
local id = 0;
local ttl = 100;
local now = ngx.time();
local config = ngx.shared.config;
if not config:get("id") then
config:set("id", "0");
end
while id >= tonumber(config:get("id")) do
local ttl = math.random(ttl - 10, ttl + 10);
if ngx.time() - now > ttl then
break;
end
ngx.sleep(1);
end
ngx.say("OK");
}
...
}注:为了解决服务端不知道客户端何时断开连接的情况,代码中引入超时机制。
其次,我们需要做一些基础工作,以便操作Nginx的共享内存:
lua_shared_dict config 1m;
server {
location /config {
content_by_lua '
local config = ngx.shared.config;
if ngx.var.request_method == "GET" then
local field = ngx.var.arg_field;
if not field then
ngx.exit(ngx.HTTP_BAD_REQUEST);
end
local content = config:get(field);
if not content then
ngx.exit(ngx.HTTP_BAD_REQUEST);
end
ngx.say(content);
ngx.exit(ngx.HTTP_OK);
end
if ngx.var.request_method == "POST" then
ngx.req.read_body();
local args = ngx.req.get_post_args();
for field, value in pairs(args) do
if type(value) ~= "table" then
config:set(field, value);
end
end
ngx.say("OK");
ngx.exit(ngx.HTTP_OK);
end
';
}
...
}如果要写Nginx共享内存的话,可以这样操作:
shell> curl -d id=123 http:///config
如果要读Nginx共享内存的话,可以这样操作:
shell> curl http:///config?field=id
注:实际应用时,应该加上权限判断逻辑,比如只有限定的IP地址才能使用此功能。
当数据库有新数据的时候,可以通过触发器来写Nginx共享内存,当然,在应用层通过观察者模式来写Nginx共享内存通常会是一个更优雅的选择。
如此一来,数据库就彻底翻身做主人了,虽然系统仍然存在轮询,但已经从轮询别人变成了轮询自己,效率不可相提并论,相应的,我们可以加快轮询的频率而不会造成太大的压力,从而在根本上提升用户体验。
突然想起另一个有趣的服务端推的做法,不妨在一起唠唠:如果DB使用Redis的话,那么可以利用其提供的BLPOP方 法来实现服务端推,这样的话,连sleep都不用了,不过有一点需要注意的是,一旦使用了BLPOP方法,那么Nginx和Redis之间的连接便会一直 保持下去,从Redis的角度看,Nginx是客户端,而客户端的可用端口数量是有限的,这就意味着一台Nginx至多只能建立五六万个连接 (net.ipv4.ip_local_port_range),有点儿少。
…
当然,本文的描述只是沧海一粟,还有很多技术可供选择,比如Pub/Sub,WebSocket等等,篇幅所限,这里就不多说了,有兴趣的读者请自己查阅。
[转] 消息系统该Push/Pull模式分析的更多相关文章
- 基于long pull实现简易的消息系统参考
我们都用过消息中间件,它的作用自不必多说.但对于消费者却一直有一些权衡,就是使用push,还是pull模式的问题,这当然是各有优劣.当然,这并不是本文想讨论的问题.我们想在不使用长连接的情意下,如何实 ...
- 分布式开放消息系统(RocketMQ)的原理与实践
分布式消息系统作为实现分布式系统可扩展.可伸缩性的关键组件,需要具有高吞吐量.高可用等特点.而谈到消息系统的设计,就回避不了两个问题: 消息的顺序问题 消息的重复问题 RocketMQ作为阿里开源的一 ...
- kafka:一个分布式消息系统
1.背景 最近因为工作需要,调研了追求高吞吐的轻量级消息系统Kafka,打算替换掉线上运行的ActiveMQ,主要是因为明年的预算日流量有十亿,而ActiveMQ的分布式实现的很奇怪,所以希望找一个适 ...
- Kafka——分布式消息系统
Kafka——分布式消息系统 架构 Apache Kafka是2010年12月份开源的项目,采用scala语言编写,使用了多种效率优化机制,整体架构比较新颖(push/pull),更适合异构集群. 设 ...
- 分布式消息系统Kafka初步
终于可以写kafka的文章了,Mina的相关文章我已经做了索引,在我的博客中置顶了,大家可以方便的找到.从这一篇开始分布式消息系统的入门. 在我们大量使用分布式数据库.分布式计算集群的时候,是否会遇到 ...
- 消息系统Kafka介绍 - 董的博客
1. 概述 Kafka是Linkedin于2010年12月份开源的消息系统,它主要用于处理活跃的流式数据.活跃的流式数据在web网站应用中非常常见,这些数据包括网站的pv.用户访问了什么内容,搜索了 ...
- KAFKA分布式消息系统
2015-01-05 大数据平台 Hadoop大数据平台 基本概念 kafka的工作方式和其他MQ基本相同,只是在一些名词命名上有些不同.为了更好的讨论,这里对这些名词做简单解释.通过这些解释应该可以 ...
- 【转载】Apache Kafka:下一代分布式消息系统
http://www.infoq.com/cn/articles/kafka-analysis-part-1 Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩 ...
- 消息系统Kafka介绍
1. 概述 Kafka是Linkedin于2010年12月份开源的消息系统,它主要用于处理活跃的流式数 据.活跃的流式数据在web网站应用中非常常见,这 些数据包括网站的pv.用户访问了什么内容,搜 ...
随机推荐
- js登录页面的 回车事件
js登录页面的 回车事件 js登录页面的 回车事件(2012-12-26 10:37:03)转载▼标签: jseventkey回车事件登录 分类: js.jquery //回车事件 第一种docum ...
- php基础知识【函数】(4)时间date
一.time() -- 返回当前的 Unix 时间戳 $nextWeek = time() + (7 * 24 * 60 * 60); echo 'Next Week: '. date('Y-m-d' ...
- TCP协议握手与分手
TCP(Transmission Control Protocol) 传输控制协议 TCP的7次握手可以理解为3次握手和4次分手. TCP状态转换图,如下: 这个图N多人都知道,它对排除和定位网络或系 ...
- 研究不定数量参数的函数并实现一个printf函数
一.前提知识 1.如何传递参数(主函数) a.函数的参数是通过栈传递,而且是从右到左依次入栈 b.即使是char型变量,在传递参数时,也是占用两个字节,因为push操作是两个字节为单位的. c.sho ...
- core dump
Core Dump?! 整理:Wilbur Lang 何谓 core? 在使用半导体作为内存的材料前,人类是利用线圈当作内存的材料(发明 者为王安),线圈就叫作 core ,用线圈做的内存就叫作 co ...
- 开源java
http://code.google.com/p/nullpomino/source/checkout http://www.open-open.com/open254058.htm http://w ...
- 开始LXC,DOCKER,VAGRANT,COREOS之旅
很有兴趣哟. 有人说会重构互联基质,可能言重. 但,无疑在未来几年内,DOCKER和COREOS这样的更新布置模式会流行.
- Dp解决数组中连续子数组的最大和
#include<iostream> ]; ;i<size;i++) { TempSum = CurSum; ) ...
- Java 8 中的 Streams API 详解
为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...
- java学习面向对象之封装
在以往几节当中我们讲到了什么是类,类就是对一类事物的描述,比如现在我们有一个人类 class Person { /** *这里我们分别在name和age上加上了元素的访问权限 *这里的private是 ...