在PHP中使用Comet吗?


82

我当时在考虑使用PHP后端实现实时聊天,但在讨论彗星的网站上遇到了以下评论:

我的理解是,PHP是Comet的一种糟糕的语言,因为Comet要求您保持对每个浏览器客户端开放的持久连接。使用mod_php意味着为每个客户端完全绑定一个Apache子节点,而这根本无法扩展。我认识的从事Comet工作的人大多使用Twisted Python,该工具旨在处理数百或数千个同时连接。

这是真的?还是可以配置的东西?


4
您可以将PHP作为fastcgi运行...
Itay Moav -Malimovka,2009年

4
使用nodeJS作为服务器来保持客户端连接,使用javascript中的websocket从浏览器连接到服务器。从这个意义上讲,PHP可以是将连接到nodejs的特权客户端,推送一些将以某种方式在客户端处理的服务数据。
Artjom Kurapov 2012年

1
@ArtjomKurapov您可以使PHP成为Web服务器,从而绕过Apache处理请求的方法-将其视为处理彗星请求的真实PHP服务器。
基督教徒

@Christian,如果您是从5.4开始内置的php网络服务器,那么仅用于开发并在生产中使用它是一个坏主意
Artjom Kurapov 2012年

2
@ArtjomKurapov不,我的意思是编写一个真正的PHP服务器,方法是使用PHP套接字监听端口80并无限期阻止输入-有效地工作服务器。这已经可以在phpwebsocket等项目中看到
基督教徒

Answers:


61

同意/扩展已经说过的内容,我认为FastCGI不能解决问题。

阿帕奇

进入Apache的每个请求都将使用一个工作线程,直到请求完成为止,这对于COMET请求而言可能是很长的时间。

关于Ajaxian的这篇文章提到在Apache使用COMET,这很困难。该问题并非特定于PHP,而是适用于您可能希望在Apache上使用的任何后端CGI模块。

建议的解决方案是使用“事件” MPM模块,该模块更改将请求分配到工作线程的方式。

该MPM尝试修复HTTP中的“保持活动状态”。客户端完成第一个请求后,客户端可以保持连接打开,并使用同一套接字发送其他请求。这样可以节省创建TCP连接时的大量开销。但是,传统上Apache会保留整个子进程/线程来等待来自客户端的数据,这有其自身的缺点。为了解决此问题,此MPM使用专用线程来处理侦听套接字和处于“保持活动”状态的所有套接字。

不幸的是,这也不起作用,因为它只会请求完成后才“打s” ,等待来自客户端的新请求。

的PHP

现在,考虑问题的另一面,即使您通过在每个彗星请求中保留一个线程来解决问题,每个请求仍将需要一个PHP线程-这就是为什么FastCGI无法提供帮助。

您需要像Continuations之类的东西,它允许在观察到彗星请求的事件触发后恢复它们。AFAIK,这在PHP中是不可能的。我只在Java中看到过它-请参阅Apache Tomcat服务器

编辑:

这里有一篇有关使用负载平衡器(HAProxy)的文章,它允许您在同一服务器的端口80上同时运行apache服务器和启用了彗星的服务器(例如,jetty,tomcat for Java)。


20
我意识到这并不能完全提供解决方案:/
Mike Houston,

+1是因为Apache / PHP不是扩展彗星解决方案的好选择。PHP用户的选项是1),正如您提到的那样,疯狂地配置其他服务器和代理,或者2)使用SaaS解决方案并通过WebSync On-Demand之类的方法来卸载彗星。
jvenema 2010年

1
这在几个方面都是错误的。如果要离开每个用户一个线程的方法,则可以通过删除Apache作为中介并让PHP处理这些请求来轻松实现。当然,Apache在提供内容方面表现更好,因此,我将在不提供任何内容的子域上运行此无Apache的PHP服务器。
基督教徒

@MikeHouston尝试在IIS中用php尝试Comet吗?
ravi404 2012年

@ravz,这里有关于IIS和彗星的一些东西:stackoverflow.com/questions/1898848/comet-programming-in-iis,但是我怀疑fast-cgi PHP模块与apache具有相同的局限性。它在这里提到了一个线程环境:microsoft.com/web/platform/phponwindows.aspx-我自己不使用Windows服务器,因此我不确定线程​​模型。
迈克·休斯顿

14

您可以使用Nginx和JavaScript来实现基于Comet的聊天系统,该系统具有很高的可伸缩性,而内存或CPU利用率却很少。

我这里有一个非常简单的示例,可以帮助您入门。它涵盖了使用NHPM模块编译Nginx,并包括用于jQuery,PHP和Bash中的简单发布者/订阅者角色的代码。

http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/


10

的PHP

我发现这个有趣的小屏幕录像解释了简单的彗星。顺带一提,我真的认为这会在任何实际负载下杀死您的服务器。当只有几个用户时,我会说只需要这种解决方案。该解决方案非常易于实现(截屏仅花费您5分钟的时间:)。但是,正如我之前告诉我的,我认为这对许多并发用户并没有好处(猜想您应该对它进行基准测试),因为:

  1. 它使用的文件I / O比从内存中获取数据要慢得多。例如功能filemtime()
  2. 其次,但我不认为PHP至少没有一个不错的线程模型。无论如何,PHP并不是为此设计的,因为没有共享模型。像幻灯片上说的那样,“共享数据被下推到数据存储层”,例如MySQL。

备择方案

我真的认为,如果要进行任何彗星/长轮询,则应尝试其他方法。您可以使用多种语言,例如:

  • Java / JVM:Jetty延续
  • Python:Dustin的晃荡
  • Erlang:彗星等的流行语言。
  • Lua,Ruby,C,Perl仅举几例。

仅仅执行一个简单的Google搜索,就会向您展示很多PHP替代方案(我认为在任何大负载下它都会杀死您的服务器)。



6

您也可以尝试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();

4

我有一个类似的问题。我发现有趣的一种选择是使用现有的Comet服务器(如cometd-java或cometd-python)作为核心消息中心。这样,您的PHP代码仅仅是Comet服务器的客户端-就像其他客户端一样,它可以发布或读取通道中的消息。

这里链接了一个有趣的代码段:http : //morglog.org/?p=22=1,它实现了此方法的一部分(尽管也散布了一些调试代码)。


3

我目前正在使用套接字函数实现可扩展的PHP Comet服务器。它被称为“ phet”([ph] p com [et])

项目页面:http : //github.com/Tim-Smart/phet

免费免费加入开发。我目前设法完成了大多数服务器逻辑,只需要完成客户端的工作即可。

编辑:最近使用该pcntl_fork方法添加了“多线程”功能:)


尚无任何有关如何使用此库的示例。
脚踩

3

仅由于它固有的单线程性,您将很难在PHP中实现Comet。

查看Websync On-Demand-该服务使您可以通过服务器端发布来集成PHP,卸载繁重的并发连接内容,并可以立即创建实时聊天应用程序。




0

我认为这是一个更大的问题,因为一直有很多apache线程在运行。如果它通过apache与PHP(通常)相同的方式工作,那么任何语言都将存在。


1
我认为关键是您通常会在每个请求的进程中运行php,而不是每个请求的线程。
troelskn
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.