83

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

我的理解是 PHP 对于 Comet 来说是一种糟糕的语言,因为 Comet 要求您保持对每个浏览器客户端的持久连接。使用 mod_php 这意味着为每个根本无法扩展的客户端绑定一个全职的 Apache 孩子。我认识的从事 Comet 工作的人大多使用 Twisted Python,它旨在处理成百上千的同时连接。

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

4

11 回答 11

62

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

阿帕奇

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

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

建议的解决方案是使用'event' MPM 模块,它改变了请求被分派到工作线程的方式。

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

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

PHP

现在,考虑到问题的另一面,即使您解决了每个彗星请求保留一个线程的问题,您仍然需要每个请求一个 PHP 线程——这就是为什么 FastCGI 无济于事。

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

编辑:

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

于 2009-11-23T15:09:31.643 回答
14

您可以使用 Nginx 和 JavaScript 来实现基于 Comet 的聊天系统,该系统非常可扩展,内存或 CPU 使用率极低。

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

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

于 2010-08-27T21:29:32.503 回答
10

PHP

我发现这个有趣的小截屏视频解释了简单的彗星。作为旁注,我真的认为这会在任何实际负载下杀死您的服务器。当只有几个用户时,我会说只使用这个解决方案。这个解决方案实现起来非常简单(截屏只需要您 5 分钟的时间 :))。但正如我之前所说,我认为这对很多并发用户来说并不好(猜你应该对其进行基准测试;))因为:

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

备择方案

如果你想做任何彗星/长轮询,我真的认为你应该尝试其他选择。您可以使用多种语言,例如:

  • Java/JVM:码头延续
  • 蟒蛇:达斯汀的晃动
  • Erlang:comet/etc 的流行语言。
  • Lua、Ruby、C、Perl 仅举几例。

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

于 2009-08-24T23:26:57.897 回答
7

mod_php 不是使用 PHP 的唯一方法。你可以使用fastcgi。PHP 必须用--enable-fastcgi.

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

于 2009-03-02T17:46:20.003 回答
6

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

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

事件循环基于反应器模式(因此得名),并受到 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();
于 2013-01-21T09:54:41.887 回答
4

我有一个类似的问题。我发现有趣的一个选项是使用现有的 Comet 服务器,如 cometd-java 或 cometd-python,作为核心消息中心。然后,您的 PHP 代码只是 Comet 服务器的客户端——它可以像其他客户端一样从频道发布或读取消息。

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

于 2009-04-24T21:05:13.297 回答
3

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

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

于 2009-07-27T21:27:22.667 回答
3

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

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

免费免费加入开发。我目前已经设法完成大部分服务器逻辑,只需要完成客户端的东西。

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

于 2009-11-18T06:55:27.180 回答
1

刚刚为 nginx Web 服务器推出了一个新模块,它将允许 Comet 使用任何语言,包括 PHP。

http://www.igvita.com/2009/10/21/nginx-comet-low-latency-server-push/

于 2009-11-23T14:30:16.467 回答
1

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

PHP-彗星服务器:http: //sourceforge.net/projects/comet/

于 2010-06-23T19:51:41.153 回答
0

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

于 2009-03-02T17:48:11.420 回答