php - 长轮询/HTTP流一般问题

标签 php jquery comet long-polling http-streaming

我正在尝试使用创建一个理论上的Web聊天应用程序,已经阅读了有关长轮询和HTTP流的知识,并且设法运用了文章中介绍的大多数原理。但是,有两个主要问题仍然无法解决。
长轮询

  • 服务器如何知道何时发送更新?它需要连续查询数据库还是有更好的方法?

  • 使用HTTP流
  • 如何在Ajax连接仍处于 Activity 状态时检查结果?我知道jQuery的ajat调用的success函数,但是如何在连接仍在进行的同时检查数据

  • 我将不胜感激,谢谢您。

    最佳答案

    是的,类似 cometd 的技术通常在一开始会炸毁大脑-只是让您以不同的方式思考。另一个问题是PHP没有足够的可用资源,因为每个人都在使用node.js,Python,Java等编写Comet。

    我将尽力回答您的问题,希望它能为人们阐明这个话题。

    How will the server know when an update have been sent? will it need to query the databse continually or is there a better way?



    答案是:在最一般的情况下,您应该使用消息队列(MQ)。 Redis商店中内置的RabbitMQ或Pub/Sub功能可能是一个不错的选择,尽管市场上有许多竞争解决方案,例如ZeroMQ,Beanstalkd等。

    因此,您可以只订阅一个MQ事件并挂起,直到其他人将发布您订阅的消息,而MQ会唤醒您并发送消息,而不是连续查询数据库。聊天应用程序是了解此功能的一个很好的用例。

    我还要提到的是,如果您要搜索其他语言的Comet-chat实现,您可能会注意到简单的不使用MQ的实现。那么他们如何交换信息呢?关键是这类解决方案通常实现为独立的单线程异步服务器,因此它们可以将所有连接存储在线程本地数组(或类似的东西)中,在单个循环中处理许多连接,只选择一个并在需要时通知。这样的异步服务器实现是一种非常适合 cometd 技术的现代方法。但是,您最有可能在mod_php或FastCGI之上实现Comet,在这种情况下,这种简单方法不是您的选择,您应该使用MQ。

    这对于理解如何实现独立的异步Comet服务器以处理单个线程中的许多连接仍然非常有用。 PHP的最新版本支持Libevent和Socket Streams,因此也可以在PHP中实现这种服务器。 PHP文档中还有一个example

    How do I check for the results during the Ajax connection is still active? I'm aware of jQuery's success function for ajax calls, but how do I check the data while the connection is still ongoing?



    如果您使用普通的Ajax技术(例如纯XHR,jQuery Ajax等)进行长时间的民意测验,那么您将没有简单的方法在单个Ajax请求中传输多个响应。如您所提到的,您只有“成功”处理程序来整体处理响应,而不能部分处理。解决方法是,每个请求仅发送一个响应,并在“成功”处理程序中对其进行处理,之后,他们只需打开一个新的长轮询请求即可。这就是HTTP协议(protocol)的工作方式。

    还应该提到的是,实际上存在一种变通办法,可以使用各种技术(例如隐藏的IFRAME中的无限长页面或使用多部分HTTP响应)使用各种技术来实现类似于流的功能。这两种方法都有某些缺点(前一种方法被认为不可靠,有时可能会产生不必要的浏览器行为,例如无限加载指示符,而后一种则泄漏了一致且直接的跨浏览器支持,但是已知某些应用程序仍然可以成功地依靠该方法当浏览器无法正确处理多部分响应时,该机制会退回到长轮询)。

    如果您希望以一种可靠的方式处理每个请求/连接的多个响应,则应考虑使用更先进的技术,例如WebSocket,该技术受最新浏览器支持,或在任何支持原始套接字的平台(例如Flash或(例如,如果您是为移动应用开发的)。

    Could you please elaborate more on message queues?



    Message Queue是描述Observer pattern的独立(或内置)实现的术语(也称为“发布/订阅”或简称为PubSub)。如果您开发一个大型应用程序,那么拥有一个应用程序将非常有用-它使您可以解耦系统的不同部分,实现事件驱动的异步设计,并使您的工作变得更加轻松,尤其是在异构系统中。它在现实世界的系统中有许多应用程序,我将仅提及其中的几个:
  • 任务队列。假设我们正在编写自己的YouTube,并且需要在后台转换用户的视频文件。显然,我们应该有一个带有UI的Web应用程序来上传电影,并使用固定数量的工作进程来转换视频文件(也许我们甚至需要一些专用服务器,我们的工作人员只能离开这些服务器)。同样,我们可能不得不用C语言编写我们的工作人员,以确保获得更好的性能。我们要做的只是设置一个消息队列服务器,以收集视频转换任务并将其从Web应用程序传递给我们的工作人员。当工作程序生成时,它会连接到MQ,并空闲以等待新任务。当有人上传视频文件时,Web应用程序将连接到MQ并发布包含新作业的消息。诸如RabbitMQ之类的强大MQ可以在连接的工作人员之间平均分配任务,跟踪已完成的任务,确保不会丢失任何内容,并提供故障转移甚至管理UI来浏览当前待处理的任务和统计信息。
  • 异步行为。我们的 cometd 聊天就是一个很好的例子。显然,我们不想一直都在定期轮询数据库(那么Comet的用途是什么?-进行定期Ajax请求的区别不大)。当出现新的聊天消息时,我们希望有人通知我们。一个消息队列就是那个人。假设我们使用的是Redis键/值存储-这是一个非常出色的工具,可以在其数据存储功能中提供PubSub实现。最简单的情况如下所示:
  • 有人进入聊天室后,将发出新的Ajax长轮询请求。
  • 服务器端的
  • 请求处理程序向Redis发出命令以订阅“newmessage” channel 。
  • 一旦有人在聊天中输入消息,服务器端处理程序就会将消息发布到Redis的“newmessage”主题中。
  • 消息发布后,Redis将立即通知所有之前订阅该 channel 的未决处理程序。
  • 在收到通知后,可使长时间轮询请求保持打开状态的PHP代码可以返回带有新聊天消息的请求,因此将通知所有用户。他们可以在那一刻从数据库中读取新消息,或者可以直接在消息有效负载内部传输消息。

  • 我希望我的插图易于理解,但是消息队列是一个非常广泛的主题,因此请引用上面提到的资源以进一步阅读。

    关于php - 长轮询/HTTP流一般问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7213549/

    相关文章:

    jquery - 无法让 ScrollTo jquery 插件工作?

    php - 用于匹配传递的函数/方法参数的正则表达式

    php - 如何检测 stream_copy_to_stream 错误?

    javascript - jQuery 数据表 - 选择列内的列表

    jquery - 使用 JQuery 仅显示/隐藏一个 DIV

    http - 为什么 Comet 需要分块编码响应?

    c# - cometd 性能问题

    http - 使用 Comet/持久 HTTP 连接时,客户端和后端有哪些缺点?

    php - 动态设置 PDO 的 PARAM 类型

    php - 按两个字段排序