我当时在考虑使用PHP后端实现实时聊天,但在讨论彗星的网站上遇到了以下评论:
我的理解是,PHP是Comet的一种糟糕的语言,因为Comet要求您保持对每个浏览器客户端开放的持久连接。使用mod_php意味着为每个客户端完全绑定一个Apache子节点,而这根本无法扩展。我认识的从事Comet工作的人大多使用Twisted Python,该工具旨在处理数百或数千个同时连接。
这是真的?还是可以配置的东西?
我当时在考虑使用PHP后端实现实时聊天,但在讨论彗星的网站上遇到了以下评论:
我的理解是,PHP是Comet的一种糟糕的语言,因为Comet要求您保持对每个浏览器客户端开放的持久连接。使用mod_php意味着为每个客户端完全绑定一个Apache子节点,而这根本无法扩展。我认识的从事Comet工作的人大多使用Twisted Python,该工具旨在处理数百或数千个同时连接。
这是真的?还是可以配置的东西?
Answers:
同意/扩展已经说过的内容,我认为FastCGI不能解决问题。
进入Apache的每个请求都将使用一个工作线程,直到请求完成为止,这对于COMET请求而言可能是很长的时间。
关于Ajaxian的这篇文章提到在Apache上使用COMET,这很困难。该问题并非特定于PHP,而是适用于您可能希望在Apache上使用的任何后端CGI模块。
建议的解决方案是使用“事件” MPM模块,该模块更改将请求分配到工作线程的方式。
该MPM尝试修复HTTP中的“保持活动状态”。客户端完成第一个请求后,客户端可以保持连接打开,并使用同一套接字发送其他请求。这样可以节省创建TCP连接时的大量开销。但是,传统上Apache会保留整个子进程/线程来等待来自客户端的数据,这有其自身的缺点。为了解决此问题,此MPM使用专用线程来处理侦听套接字和处于“保持活动”状态的所有套接字。
不幸的是,这也不起作用,因为它只会在请求完成后才“打s” ,等待来自客户端的新请求。
现在,考虑问题的另一面,即使您通过在每个彗星请求中保留一个线程来解决问题,每个请求仍将需要一个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()
,我真的认为,如果要进行任何彗星/长轮询,则应尝试其他方法。您可以使用多种语言,例如:
仅仅执行一个简单的Google搜索,就会向您展示很多PHP替代方案(我认为在任何大负载下它都会杀死您的服务器)。
您也可以尝试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();
我有一个类似的问题。我发现有趣的一种选择是使用现有的Comet服务器(如cometd-java或cometd-python)作为核心消息中心。这样,您的PHP代码仅仅是Comet服务器的客户端-就像其他客户端一样,它可以发布或读取通道中的消息。
这里链接了一个有趣的代码段:http : //morglog.org/?p=22=1,它实现了此方法的一部分(尽管也散布了一些调试代码)。
我目前正在使用套接字函数实现可扩展的PHP Comet服务器。它被称为“ phet”([ph] p com [et])
项目页面:http : //github.com/Tim-Smart/phet
免费免费加入开发。我目前设法完成了大多数服务器逻辑,只需要完成客户端的工作即可。
编辑:最近使用该pcntl_fork
方法添加了“多线程”功能:)
仅由于它固有的单线程性,您将很难在PHP中实现Comet。
查看Websync On-Demand-该服务使您可以通过服务器端发布来集成PHP,卸载繁重的并发连接内容,并可以立即创建实时聊天应用程序。
刚刚为Nginx Web服务器推出了一个新模块,该模块将允许Comet支持任何语言,包括PHP。
http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/
您将必须使用PHP创建自己的服务器。使用Apache / mod_php或什至fastcgi根本无法扩展。几年了,但是可以帮助您入门:
PHP-Comet-Server:http: //sourceforge.net/projects/comet/