在 PHP 中使用彗星?

Posted

技术标签:

【中文标题】在 PHP 中使用彗星?【英文标题】:Using comet with PHP? 【发布时间】:2010-10-10 19:58:53 【问题描述】:

我正在考虑使用 php 后端实现实时聊天,但我在一个讨论彗星的网站上看到了这条评论:

我的理解是 PHP 是一个 彗星的可怕语言,因为 Comet 要求你保持一个 对每个人开放的持久连接 浏览器客户端。使用 mod_php 这个 意味着捆绑一个 Apache 孩子 全职为每个客户 根本无法扩展。我的人 知道做彗星的东西大多是 使用设计的 Twisted Python 处理成百上千的 同时连接。

这是真的吗?或者它是可以配置的?

【问题讨论】:

你可以将php作为fastcgi运行... 使用nodeJS作为服务器来保持客户端连接,javascript中的websockets从浏览器连接到服务器。从这个意义上说,PHP 可以是一个特权客户端,它将连接到 nodejs,推送一些将在客户端以某种方式处理的服务数据。 @ArtjomKurapov 你可以将 PHP 变成一个 Web 服务器,从而绕过 Apache 处理请求的方法 - 把它想象成一个真正的 PHP 服务器处理彗星请求 @Christian 如果您的意思是自 5.4 以来内置 php 网络服务器,那么它仅用于开发并在生产中使用它是一个坏主意 @ArtjomKurapov 不,我的意思是编写一个真正的 PHP 服务器,通过使用 PHP 套接字来监听端口 80 并无限期地阻止输入 - 有效地服务器如何工作。这可以在 phpwebsocket 等项目中看到。 【参考方案1】:

同意/扩展已经说过的话,我认为 FastCGI 不会解决问题。

阿帕奇

对 Apache 的每个请求都将使用一个工作线程,直到请求完成,这对于 COMET 请求来说可能需要很长时间。

This article on Ajaxian 提到在 Apache 上使用 COMET,这很困难。该问题并非特定于 PHP,而是适用于您可能希望在 Apache 上使用的任何后端 CGI 模块。

建议的解决方案是使用'event' MPM module,它改变了将请求分派到工作线程的方式。

此 MPM 尝试修复 HTTP 中的“存活问题”。 客户完成第一个后 请求,客户端可以保留 连接打开,并进一步发送 请求使用相同的套接字。这 可以节省大量开销 创建 TCP 连接。然而, Apache 传统上保留一个完整的 子进程/线程等待数据 来自客户,它带来了自己的 缺点。为了解决这个问题, 此 MPM 使用专用线程 处理两个监听套接字,和 Keep Alive 中的所有套接字 状态。

不幸的是,这也不起作用,因为它只会在请求完成后“暂停”,等待来自客户端的新请求。

PHP

现在,考虑到问题的另一面,即使您解决了每个彗星请求保留一个线程的问题,您仍然需要每个请求一个 PHP 线程 - 这就是为什么 FastCGI 无济于事。

您需要像Continuations 这样的东西,它允许在观察到彗星请求被触发的事件时恢复它们。 AFAIK,这在 PHP 中是不可能的。我只在 Java 中看到过 - 请参阅 Apache Tomcat server。

编辑:

有一个 article here 关于使用负载平衡器 (HAProxy) 允许您在同一服务器的端口 80 上同时运行 apache 服务器和启用彗星的服务器(例如,jetty、tomcat for Java)。

【讨论】:

我意识到这并不能完全提供解决方案:/ +1 因为 Apache/PHP 不是扩展彗星解决方案的好选择。 PHP 用户的选项是 1) 正如您所提到的,额外服务器和代理的疯狂配置或 2) 使用 SaaS 解决方案并通过 WebSync On-Demand 之类的方式卸载彗星的东西。 这在几个方面是错误的。如果想放弃每用户一个线程的方法,可以通过去掉 Apache 作为中介,让 PHP 处理这些请求来轻松实现。当然,Apache 在提供内容方面工作得更好,所以我会在不提供任何内容的子域上运行这个没有 apache 的 PHP 服务器。 @MikeHouston 在 IIS 中用 php 尝试彗星怎么样? @ravz,这里有一些关于 IIS 和 Comet 的资料:***.com/questions/1898848/comet-programming-in-iis,但我怀疑 fast-cgi PHP 模块与 apache 有相同的限制。它在这里提到了一个单线程环境:microsoft.com/web/platform/phponwindows.aspx - 我自己不使用 Windows 服务器,所以我不确定线程​​模型。【参考方案2】:

您可以使用 nginx 和 JavaScript 来实现一个基于 Comet 的聊天系统,该系统的可扩展性非常好,内存或 CPU 使用率极低。

我在这里有一个非常简单的示例,可以帮助您入门。它涵盖了使用 NHPM 模块编译 Nginx,并包含 jQuery、PHP 和 Bash 中简单发布者/订阅者角色的代码。

http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/

【讨论】:

【参考方案3】:

PHP

我发现这个有趣的小 screencasts 解释了简单的彗星。作为旁注,我真的认为这会在任何实际负载下杀死您的服务器。当只有几个用户时,我会说只使用这个解决方案。这个解决方案实现起来非常简单(截屏只需要您 5 分钟的时间 :))。但正如我之前所说,我认为这对很多并发用户来说并不好(猜你应该对其进行基准测试;))因为:

    它使用文件 I/O,这比从内存中获取数据要慢得多。比如函数filemtime(), 第二,但我认为至少 PHP 没有一个像样的线程模型。由于share nothing model,PHP 并不是为此而设计的。就像幻灯片上所说的“共享数据被下推到数据存储层”,例如 mysql

替代方案

如果你想做彗星/长轮询,我真的认为你应该尝试其他选择。您可以使用多种语言,例如:

Java/JVM:码头continuations。 Python:达斯汀的slosh。 Erlang:comet/etc 的流行语言。 Lua、Ruby、C、Perl 仅举几例。

只需执行一个简单的谷歌搜索,就会向您展示许多 PHP 替代方案(我认为在任何大负载下都会杀死您的服务器)。

【讨论】:

【参考方案4】:

mod_php 不是使用 PHP 的唯一方法。你可以使用fastcgi。 PHP 必须用--enable-fastcgi 编译。

PHP 作为 FastCGI:http://www.fastcgi.com/drupal/node/5?q=node/10

【讨论】:

【参考方案5】:

你也可以试试https://github.com/reactphp/react

React 是 PHP 中用于事件驱动编程的低级库。它的核心是一个事件循环,在它之上它提供了低级实用程序,例如:流抽象、异步 dns 解析器、网络客户端/服务器、http 客户端/服务器、与进程的交互。第三方库可以使用这些组件来创建异步网络客户端/服务器等等。

事件循环基于反应器模式(因此得名),并受到 EventMachine (Ruby)、Twisted (Python) 和 Node.js (V8) 等库的强烈启发。

介绍性示例显示了一个简单的 HTTP 服务器侦听端口 1337:

<?php

$i = 0;

$app = function ($request, $response) use (&$i) 
    $i++;

    $text = "This is request number $i.\n";
    $headers = array('Content-Type' => 'text/plain');

    $response->writeHead(200, $headers);
    $response->end($text);
;

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);

$http->on('request', $app);

$socket->listen(1337);
$loop->run();

【讨论】:

【参考方案6】:

我遇到了类似的问题。我发现一个有趣的选项是使用现有的 Comet 服务器,如 cometd-java 或 cometd-python,作为核心消息中心。然后,您的 PHP 代码只是 Comet 服务器的客户端——它可以像其他客户端一样从频道发布或读取消息。

这里有一个有趣的代码 sn-p 链接:http://morglog.org/?p=22=1,它实现了此方法的一部分(尽管也有一些调试代码散布在各处)。

【讨论】:

【参考方案7】:

我目前正在使用套接字函数实现一个可扩展的 PHP Comet 服务器。它被称为“phet”([ph]p com[et])

项目页面:http://github.com/Tim-Smart/phet

免费免费加入开发。我目前已经设法完成大部分服务器逻辑,只需要完成客户端的东西。

编辑:最近使用pcntl_fork 方法添加了“多线程”功能:)

【讨论】:

没有关于如何使用这个库的现成示例。【参考方案8】:

您将很难在 PHP 中实现 comet,因为它具有固有的单线程特性。

查看Websync On-Demand - 该服务可让您通过服务器端发布集成 PHP,卸载繁重的并发连接,并让您立即创建实时聊天应用程序。

【讨论】:

【参考方案9】:

刚刚为 nginx Web 服务器推出了一个新模块,它将允许 Comet 使用任何语言,包括 PHP。

http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/

【讨论】:

【参考方案10】:

您必须在 PHP 中创建自己的服务器。使用 Apache/mod_php 甚至 fastcgi 根本无法扩展。几年前,但可以让你开始:

PHP 彗星服务器: http://sourceforge.net/projects/comet/

【讨论】:

【参考方案11】:

我认为这更像是一个问题,因为有很多 apache 线程一直在运行是一个问题。如果它以与 PHP(通常)相同的方式通过 apache 工作,那么任何语言都将存在。

【讨论】:

我认为关键是您通常在每个请求的进程中运行 php,而不是每个请求的线程。

以上是关于在 PHP 中使用彗星?的主要内容,如果未能解决你的问题,请参考以下文章

使用 php 和 jquery 的简单彗星示例

彗星与 php 套接字服务器?

AJAX 进度条 - 轮询,彗星?

为java选择彗星框架

iframe 中的彗星服务器数据是不是只是累积?

jQuery彗星推送,没有彗星服务器