[转] 消息系统该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.用户访问了什么内容,搜 ...
随机推荐
- javascript 设为首页 | 加入收藏夹 JS代码
我们介绍一个可兼容所有浏览器的加入收藏代码代码,大概原理是这样的我们根据获取用户navigator.userAgent.toLowerCase()信息来判断浏览器,根据浏览器是否支持加入收藏js命令, ...
- MAC 开发工具
web开发编辑器 Espresso下载地址 密码: i9hr
- 小A项目为什么加班
1.负责架构搭建的人搭建完成架构后,没有进行落地性验证:导致真正要用到的时候才发现spring没有配置:需要对架构人员的进度和内容进行跟踪,在跟踪进度的时候需要强调落地性: 2.负责架构搭建的人没有提 ...
- isKindOfClass:和isMemberOfClass:-b
isKindOfClass: Returns a Boolean value that indicates whether the receiver is an instance of given c ...
- 2.JQuery AJAX
new ActiveXObject("Microsoft XMLHTTP")是IE中创建XMLHTTPRequest对象的方法.非IE浏览器创建方法是new XmlHttpRequ ...
- Java实现二叉树的构建与遍历
转载:http://ocaicai.iteye.com/blog/1047397 目录: 1.把一个数组的值赋值给一颗二叉树 2.具体代码 1.树的构建方法 2.具体代码 package tree; ...
- 关于type check的定义
Concept: Type Checking There is no static type checking in Scheme; type checking is done at run time ...
- 1027. Colors in Mars (20) PAT
题目:http://pat.zju.edu.cn/contests/pat-a-practise/1027 简单题,考察十进制数和n进制数的转换和输出格式的控制. People in Mars rep ...
- awk文本处理--二维数组使用一例
群友出的题: 原始文件: $ cat fileBJ30 26BJ30 24BJ30 63BJ30 70SH41 21SH41 30SH41 25SH41 25SH41 29SD15 34SD15 46 ...
- Android 金融项目整理
本来是安安心心周末休假的时间,却被强征来加班.魔都今天雾霾严重,窗外都看不到360无死角都能看到的东方明珠.吃完午饭后睡一觉起来,觉得该给自己做点事情了.那就把项目里面的一些可圈可点的技术都罗列出来, ...