`
m635674608
  • 浏览: 5053492 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

消息系统该Push/Pull模式分析

 
阅读更多

消息系统该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模型 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

        因为服务端不会主动告诉客户端它是否有新数据,所以Polling的实时性较差。虽然可以通过加快轮询频率的方式来缓解这个问题,但相应付出的代价也不小:一来会使负载居高不下,二来也会让带宽捉襟见肘。

        再来说说Long Polling,如果使用传统的LAMP技术去实现的话,大致如下所示:

    Long Polling

    Long Polling

        客户端不会频繁的轮询服务端,而是对服务端发起一个长连接,服务端通过轮询数据库来确定是否有新数据,一旦发现新数据便给客户端发出响应,这次交互便结束了。客户端处理好新数据后再重新发起一个长连接,如此周而复始。

        在上面这个Long Polling方案里,我们解决了Polling中客户端轮询造成的负载和带宽的问题,但是依然存在服务端轮询,数据库的压力可想而知,此时我们虽然可以通过针对数据库使用主从复制,分片等技术来缓解问题,但那毕竟只是治标不治本。

        我们的目标是实现一个简单的服务端推方案,但简单绝对不意味着简陋,轮询数据库是不可以接受的,下面我们来看看如何解决这个问题。在这里我们放弃了传统的LAMP技术,转而使用Nginx与Lua来实现。

    Modified Long Polling

    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/SubWebSocket等等,篇幅所限,这里就不多说了,有兴趣的读者请自己查阅。

     

    http://blog.csdn.net/jeamking/article/details/49582899

分享到:
评论

相关推荐

    zeroMQ/jzmq java例子

    在Java中,你可以使用`ZMQ.proxy()`方法创建一个代理,它可以连接req/rep、pub/sub和push/pull模式,实现消息在不同节点间的路由。 5. **多数据源**: 在实际应用中,可能会有多个数据源或消费者。ZeroMQ允许通过...

    水晶报表pull和push方法实现源代码

    水晶报表(Crystal Reports)是SAP公司的一款强大的报表设计工具,广泛应用于企业级的数据报告和分析。在水晶报表中,"Pull"和"Push"方法是两种不同的数据获取策略,它们各自有着不同的特点和应用场景。 1. **Pull...

    crystal report push模式

    在 Crystal Reports 中,有两种主要的数据访问模式:Pull 模式和 Push 模式。本篇将详细讲解 Crystal Report 的 Push 模式及其相关知识点。 Push 模式,也称为数据推送模式,是一种由应用程序控制数据流的方式。在 ...

    论文:实例对比push 和pull

    这导致AJAX应用通常采用“拉取”(Pull)模式,即客户端基于预定义的时间间隔主动请求最新的更新数据。 - **研究目的**:本论文旨在探讨浏览器基础应用的根本限制,并分析AJAX技术中的推送(Push)解决方案。通过比较...

    水晶报表Pull和Push实例源码

    2. Push模式(推送模式):与Pull模式相反,Push模式是由数据源主动将数据推送到报表。通常,这需要数据源支持订阅或者触发机制。报表只接收已经筛选和处理过的数据,降低了服务器压力,提高了性能。但这种方式的...

    pullstreams是一个简单的流模式用于学习pullstreams

    7. **实践应用**:在实际项目中,pull-streams可以用于构建自定义的文件系统操作、网络协议解析、数据流分析等场景。 通过以上内容,我们可以看到pull-streams在JavaScript编程中的独特地位,以及学习和掌握它们...

    C#web水晶报表Push模式

    C# Web开发中,水晶报表提供了两种主要的工作模式:Push模式和Pull模式。本篇文章将重点探讨C# Web水晶报表的Push模式。 Push模式,也称为服务器驱动模式,是水晶报表的一种工作方式。在这种模式下,服务器主动地将...

    JAVA移动应用程序开发对于PUSH技术的运用分析.pdf

    JAVA移动应用程序开发对于PUSH技术的运用分析 JAVA移动应用程序开发对于PUSH技术的运用分析是基于J2ME平台的移动应用程序开发中的一种重要技术。PUSH技术是一种新兴技术,基于C/S模式,可以实现将服务器中的相关...

    zeromq 代理模式的一些问题

    在这种模式中,数据从推节点(Push)流向拉节点(Pull),保证了数据的单向流动。可能出现的问题包括数据堆积在推节点,或者拉节点处理速度慢导致的阻塞。 在实际应用中,代理模式可能遇到的问题还包括: - **...

    zeromq网络开发库

    4. **负载均衡**:在PUSH/PULL模式下,ZeroMQ可以自动实现负载均衡,将任务分发到多个工作线程或节点。 5. **容错机制**:ZeroMQ具有一定的容错能力,例如,在REQ/REP模式下,如果接收方崩溃,发送方会收到一个错误...

    水晶报表PUSH模式

    2. 实时性要求不高:对于需要实时更新的动态报表,PULL模式(即按需拉取数据)可能更为适合,因为它只在需要时从服务器获取最新数据。 水晶报表提供了一种灵活的方式来选择数据处理模式,用户可以根据实际需求和...

    阿里消息 Rocketmq3.1.1安装包(包含源码)

    Pull模式下,消费者主动拉取消息。 5. **强大的管理工具**:RocketMQ提供了一套完整的管理工具,包括监控、运维、调优等功能,帮助用户更好地管理和维护消息服务。 6. **扩展性**:RocketMQ的开放源码特性使其具备...

    水晶报表push模式视频教程

    在水晶报表中,push模式是一种数据处理方式,与pull模式相对。在push模式下,数据源主动将数据推送到报表,而不是由报表从数据源拉取。这种方式在某些场景下特别有用,比如当数据量庞大或实时性要求高时,可以减少...

    水晶报表的2种模式介绍

    在水晶报表中,有两种主要的工作模式:Pull模式和Push模式。这两种模式各有特点,适用于不同的场景,对初学者来说,了解它们的区别至关重要。 Pull模式(拉模式): Pull模式是水晶报表的主动查询模式。在这种模式...

    ZeroMQ 消息通信库_共同学习2.zip

    3. **模式丰富**: ZeroMQ支持多种消息传递模式,如发布/订阅(Pub/Sub)、请求/响应(Req/Rep)、推送/拉取(Push/Pull)以及对等(Pair),这些模式为不同类型的通信场景提供了灵活性。 4. **错误恢复**: ZeroMQ...

    水晶报表 push模式(推模式)

    在水晶报表中,“推模式”(Push Mode)是一种数据检索策略,它与“拉模式”(Pull Mode)相对应,是理解水晶报表工作原理的关键概念。 **推模式详解:** 推模式,顾名思义,是数据源主动将数据“推送”到报表的...

    ZeroMQ资料

    4. **PUSH/PULL(推送/拉取)模式**:PUSH端向PULL端发送数据,PULL端按需拉取。这种模式适合处理批处理任务和流水线作业,可以实现数据的异步传输。 ZeroMQ的另一个亮点是其强大的性能和可伸缩性。由于零拷贝技术...

    ZeroMQ 云时代极速消息通信库

    - **推/拉(Push/Pull)**:生产者推送数据,消费者拉取数据。适用于数据流处理和工作队列。 - **对等(Pair)**:提供一对一的双向通信,用于低延迟、高可靠性的通信。 **4. 应用场景** - **分布式计算**:通过 ...

    Ciao-Go 云集成化先进编排工具

    通过这套新方案,企业客户能够将各类元素汇聚至单一模式当中 —— 包括云分析(例如 Hadoop 或者 Apache Spark)。Ciao 中的全部通信皆使用简单与安全节点传输协议(简称 SSNTP),同时利用 TLS 以保护不同组件间的...

Global site tag (gtag.js) - Google Analytics