在 PHP 中使用 comet?

我想用 PHP 后端实现实时聊天,但是我在一个讨论 Comet 的网站上看到了这条评论:

我的理解是 PHP 是一个 可怕的语言,因为 Comet 要求你保持一个 持久连接对每个 使用 mod _ php 就是绑住一个阿帕奇小孩 为每个客户提供全职服务 根本没有规模 我知道做彗星的事情 使用扭曲的 Python,这是设计 来处理成百上千的 同步连接。

这是真的吗? 或者这是可以配置的东西?

54818 次浏览

Mod _ PHP 不是使用 PHP 的唯一方法。您可以使用 fastcgi。 PHP 必须用 --enable-fastcgi编译。

PHP 作为快速 CGI: http://www.fastcgi.com/drupal/node/5?q=node/10

我认为让大量 Apache 线程一直运行是一个问题。如果它通过 apache 以与 PHP (通常)相同的方式工作,那么它将存在于任何语言中。

我也有类似的问题。我感兴趣的一个选择是使用现有的 Comet 服务器,如 cometd-java 或 cometd-python,作为核心消息集线器。PHP 代码只是 Comet 服务器的一个客户机——它可以从通道发布或读取消息,就像其他客户机一样。

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

您将很难在 PHP 中实现 comet,因为它具有固有的单线程特性。

看看 Websync 随需应变吧-这个服务可以让你通过服务器端发布集成 PHP,卸下繁重的并发连接工作,并且可以让你立刻创建一个实时聊天应用。

PHP

我发现这个有趣的小 视频解释简单的彗星。作为一个附带说明,我真的认为这将杀死您的服务器上任何真正的负载。当只有几个用户的时候,我想说的是直接使用这个解决方案。这个解决方案实现起来非常简单(截屏只占用你5分钟的时间:)。但正如我之前所说,我不认为它对大量并发用户有好处(我猜你应该对它进行基准测试;) ,因为:

  1. 它使用文件 I/O,比从内存中获取数据要慢得多,
  2. 第二,但我不认为至少 PHP 没有一个体面的线程模型。由于 一无所有的模式的原因,PHP 不是为此而设计的。就像幻灯片上说的“共享数据被下推到数据存储层”,例如 MySQL。

替代品

我真的认为,如果您想进行任何 comet/长轮询,应该尝试其他选项。你可以使用很多语言,比如:

  • Java/JVM: Jetty 延续.
  • 达斯汀的 哗啦
  • Erlang: Comet/etc 的流行语言。
  • Lua、 Ruby、 C、 Perl 等等。

只是执行一个简单的谷歌搜索,将显示您很多选择也 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/

同意/扩展已经说过的话,我不认为 FastCGI 将解决这个问题。

阿帕奇人

Apache 中的每个请求都将使用一个工作线程,直到请求完成,这对于 COMET 请求来说可能需要很长时间。

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

建议的解决方案是使用 “事件”MPM 模块,它改变了向工作线程发送请求的方式。

这个 MPM 试图解决 HTTP 中的‘ keep alive problem’。 在客户完成第一个 请求,客户端可以保留 连接打开,并进一步发送 请求使用相同的套接字 可以节省大量的开销 创建 TCP 连接, 传统上,阿帕奇会保留一个 等待数据的子进程/线程 从客户端,这带来了自己的 为了解决这个问题, 这个 MPM 使用一个专用线程来 处理两个监听插座,以及 所有保持生存的插座 国家。

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

PHP

现在,考虑到问题的另一面,即使解决了为每个彗星请求保留一个线程的问题,每个请求仍然需要一个 PHP 线程——这就是 FastCGI 无法提供帮助的原因。

您需要类似于 延续的东西,它允许在观察到彗星请求被触发时继续彗星请求。AFAIK,这在 PHP 中是不可能的。我只在 Java 中看到过-看看 Apache Tomcat 服务器

编辑:

有一个关于使用负载平衡器(HAProxy)的 文章,它允许您在同一台服务器的端口80上运行 apache 服务器和支持 comet 的服务器(例如 jetty,tomcat for Java)。

您必须用 PHP 创建自己的服务器。使用 Apache/mod _ php 甚至 fastcgi 根本无法扩展。几年前,但可以让你开始:

PHP-Comet-Server: Http://sourceforge.net/projects/comet/

您可以使用 Nginx 和 JavaScript 来实现一个基于 Comet 的聊天系统,该系统可伸缩性很好,内存或 CPU 利用率很低。

我这里有一个非常简单的例子,可以让你们开始。它涵盖了使用 NHPM 模块编译 Nginx,并包括 jQuery、 PHP 和 Bash 中简单的发布者/订阅者角色的代码。

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

你也可以试试 https://github.com/reactphp/react

React 是一个低级的 PHP 事件驱动程式设计库。它的核心是一个事件循环,在这个循环之上提供低级实用程序,比如: Streams 抽象、异步 dns 解析器、网络客户机/服务器、 http 客户机/服务器、与进程的交互。第三方库可以使用这些组件创建异步网络客户端/服务器等。

事件循环基于反应器模式(因此得名) ,并受到 EventMachine (Ruby)、 Twsted (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();