在 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 中使用彗星?的主要内容,如果未能解决你的问题,请参考以下文章