我正在考虑使用PHP后端实现实时聊天,但我在讨论彗星的网站上遇到了这个评论:
我的理解是,对于Comet来说,PHP是一种可怕的语言,因为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服务器和启用Comet的服务器(例如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分钟的时间:)).但正如我之前所说,我不认为它对很多并发用户有好处(猜猜你应该对它进行基准测试;))因为:
它使用的文件I/O比从内存中获取数据要慢得多.比如功能filemtime()
,
其次,但我不认为PHP没有一个像样的线程模型.PHP无论如何都不是为此设计的,因为它没有共享模型.就像幻灯片所说的那样,"共享数据被推送到数据存储层",例如MySQL.
如果你想做任何彗星/长期投票,我真的认为你应该尝试其他选择.您可以使用多种语言,例如:
Java/JVM:Jetty 延续.
Python:达斯汀的晃动.
Erlang:彗星/等的流行语言.
Lua,Ruby,C,Perl仅举几例.
只是执行简单的谷歌搜索,将向您展示很多替代品PHP(我认为在任何大的负载将杀死您的服务器).
mod_php不是使用PHP的唯一方法.你可以使用fastcgi.必须编译PHP --enable-fastcgi
.
PHP作为FastCGI:http://www.fastcgi.com/drupal/node/5? q = node10
您也可以尝试https://github.com/reactphp/react
React是PHP中用于事件驱动编程的低级库.它的核心是一个事件循环,在它上面提供了低级实用程序,例如:Streams抽象,async dns解析器,网络客户机/服务器,http客户机/服务器,与进程的交互.第三方库可以使用这些组件来创建异步网络客户端/服务器等.
事件循环基于reactor模式(因此得名),并受到诸如EventMachine(Ruby),Twisted(Python)和Node.js(V8)等库的强烈启发.
介绍性示例显示了一个侦听端口1337的简单HTTP服务器:
'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();