我正在考虑使用 PHP 后端实现实时聊天,但我在一个讨论彗星的网站上遇到了这个评论:
我的理解是 PHP 对于 Comet 来说是一种糟糕的语言,因为 Comet 要求您保持对每个浏览器客户端的持久连接。使用 mod_php 这意味着为每个根本无法扩展的客户端绑定一个全职的 Apache 孩子。我认识的从事 Comet 工作的人大多使用 Twisted Python,它旨在处理成百上千的同时连接。
这是真的?或者它是可以配置的东西?
同意/扩展已经说过的话,我认为 FastCGI 不会解决问题。
对 Apache 的每个请求都将使用一个工作线程,直到请求完成,这对于 COMET 请求可能需要很长时间。
这篇关于 Ajaxian的文章提到在 Apache 上使用 COMET,这很困难。该问题并非特定于 PHP,而是适用于您可能希望在 Apache 上使用的任何后端 CGI 模块。
建议的解决方案是使用'event' MPM 模块,它改变了请求被分派到工作线程的方式。
此 MPM 尝试修复 HTTP 中的“保持活动状态”问题。客户端完成第一个请求后,客户端可以保持连接打开,并使用同一个套接字发送更多请求。这可以在创建 TCP 连接时节省大量开销。然而,Apache 传统上让整个子进程/线程等待来自客户端的数据,这也带来了自身的缺点。为了解决这个问题,这个 MPM 使用一个专用线程来处理 Listening 套接字和所有处于 Keep Alive 状态的套接字。
不幸的是,这也不起作用,因为它只会在请求完成后“打盹” ,等待来自客户端的新请求。
现在,考虑到问题的另一面,即使您解决了每个彗星请求保留一个线程的问题,您仍然需要每个请求一个 PHP 线程——这就是为什么 FastCGI 无济于事。
您需要类似Continuations的东西,它允许在观察到它们触发的事件时恢复彗星请求。AFAIK,这在 PHP 中是不可能的。我只在 Java 中见过它——请参阅 Apache Tomcat 服务器。
编辑:
这里有一篇关于使用负载平衡器 ( HAProxy ) 的文章,允许您在同一服务器的 80 端口上同时运行 apache 服务器和启用彗星的服务器(例如,jetty、tomcat for Java)。
您可以使用 Nginx 和 JavaScript 来实现基于 Comet 的聊天系统,该系统非常可扩展,内存或 CPU 使用率极低。
我在这里有一个非常简单的示例,可以帮助您入门。它涵盖了使用 NHPM 模块编译 Nginx,并包含 jQuery、PHP 和 Bash 中简单发布者/订阅者角色的代码。
http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/
我发现这个有趣的小截屏视频解释了简单的彗星。作为旁注,我真的认为这会在任何实际负载下杀死您的服务器。当只有几个用户时,我会说只使用这个解决方案。这个解决方案实现起来非常简单(截屏只需要您 5 分钟的时间 :))。但正如我之前所说,我认为这对很多并发用户来说并不好(猜你应该对其进行基准测试;))因为:
filemtime()
,如果你想做任何彗星/长轮询,我真的认为你应该尝试其他选择。您可以使用多种语言,例如:
只需执行一个简单的谷歌搜索,就会向您展示很多 PHP 替代方案(我认为在任何大负载上都会杀死您的服务器)。
mod_php 不是使用 PHP 的唯一方法。你可以使用fastcgi。PHP 必须用--enable-fastcgi
.
PHP 作为 FastCGI:http ://www.fastcgi.com/drupal/node/5?q=node/10
你也可以试试https://github.com/reactphp/react
React 是 PHP 中用于事件驱动编程的低级库。它的核心是一个事件循环,在它之上它提供了低级实用程序,例如:流抽象、异步 dns 解析器、网络客户端/服务器、http 客户端/服务器、与进程的交互。第三方库可以使用这些组件来创建异步网络客户端/服务器等。
事件循环基于反应器模式(因此得名),并受到 EventMachine (Ruby)、Twisted (Python) 和 Node.js (V8) 等库的强烈启发。
介绍性示例显示了一个侦听端口 1337 的简单 HTTP 服务器:
<?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();
我有一个类似的问题。我发现有趣的一个选项是使用现有的 Comet 服务器,如 cometd-java 或 cometd-python,作为核心消息中心。然后,您的 PHP 代码只是 Comet 服务器的客户端——它可以像其他客户端一样从频道发布或读取消息。
这里链接了一个有趣的代码片段:http: //morglog.org/ ?p=22=1 ,它实现了这个方法的一部分(尽管也有一些调试代码)。
您将很难在 PHP 中实现 comet,因为它固有的单线程特性。
查看Websync On-Demand - 该服务允许您通过服务器端发布集成 PHP,卸载繁重的并发连接内容,并让您立即创建实时聊天应用程序。
我目前正在使用套接字函数实现一个可扩展的 PHP Comet 服务器。它被称为 'phet' ( [ph]p com[et] )
项目页面:http: //github.com/Tim-Smart/phet
免费免费加入开发。我目前已经设法完成大部分服务器逻辑,只需要完成客户端的东西。
编辑:最近使用该方法添加了“多线程”功能pcntl_fork
:)
刚刚为 nginx Web 服务器推出了一个新模块,它将允许 Comet 使用任何语言,包括 PHP。
http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/
您将必须在 PHP 中创建自己的服务器。使用 Apache/mod_php 甚至 fastcgi 根本无法扩展。几年前,但可以让你开始:
PHP-彗星服务器:http: //sourceforge.net/projects/comet/
我认为这更像是一个问题,因为有很多 apache 线程一直在运行是一个问题。如果它以与 PHP(通常)相同的方式通过 apache 工作,那么任何语言都将存在。