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