【问题标题】:Using comet with PHP?在 PHP 中使用彗星?
【发布时间】:2010-10-10 19:58:53
【问题描述】:

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

我的理解是 PHP 是一个 彗星的可怕语言,因为 Comet 要求你保持一个 对每个人开放的持久连接 浏览器客户端。使用 mod_php 这个 意味着捆绑一个 Apache 孩子 全职为每个客户 根本无法扩展。我的人 知道做彗星的东西大多是 使用设计的 Twisted Python 处理成百上千的 同时连接。

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

【问题讨论】:

  • 你可以将php作为fastcgi运行...
  • 使用nodeJS作为服务器来保持客户端连接,javascript中的websockets从浏览器连接到服务器。从这个意义上说,PHP 可以是一个特权客户端,它将连接到 nodejs,推送一些将在客户端以某种方式处理的服务数据。
  • @ArtjomKurapov 你可以将 PHP 变成一个 Web 服务器,从而绕过 Apache 处理请求的方法 - 把它想象成一个真正的 PHP 服务器处理彗星请求
  • @Christian 如果您的意思是自 5.4 以来内置 php 网络服务器,那么它仅用于开发并在生产中使用它是一个坏主意
  • @ArtjomKurapov 不,我的意思是编写一个真正的 PHP 服务器,通过使用 PHP 套接字来监听端口 80 并无限期地阻止输入 - 有效地服务器如何工作。这可以在 phpwebsocket 等项目中看到。

标签: php comet


【解决方案1】:

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

阿帕奇

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

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

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

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

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

PHP

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

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

编辑:

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

【讨论】:

  • 我意识到这并不能完全提供解决方案:/
  • +1 因为 Apache/PHP 不是扩展彗星解决方案的好选择。 PHP 用户的选项是 1) 正如您所提到的,额外服务器和代理的疯狂配置或 2) 使用 SaaS 解决方案并通过 WebSync On-Demand 之类的方式卸载彗星的东西。
  • 这在几个方面是错误的。如果想放弃每用户一个线程的方法,可以通过去掉 Apache 作为中介,让 PHP 处理这些请求来轻松实现。当然,Apache 在提供内容方面工作得更好,所以我会在不提供任何内容的子域上运行这个没有 apache 的 PHP 服务器。
  • @MikeHouston 在 IIS 中用 php 尝试彗星怎么样?
  • @ravz,这里有一些关于 IIS 和 Comet 的资料:stackoverflow.com/questions/1898848/comet-programming-in-iis,但我怀疑 fast-cgi PHP 模块与 apache 有相同的限制。它在这里提到了一个单线程环境:microsoft.com/web/platform/phponwindows.aspx - 我自己不使用 Windows 服务器,所以我不确定线程​​模型。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    PHP

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

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

    替代方案

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

    • Java/JVM:码头continuations
    • Python:达斯汀的slosh
    • Erlang:comet/etc 的流行语言。
    • Lua、Ruby、C、Perl 仅举几例。

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:

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

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

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

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

            【讨论】:

            • 没有关于如何使用这个库的现成示例。
            【解决方案8】:

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

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

            【讨论】:

              【解决方案9】:

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

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

              【讨论】:

                【解决方案10】:

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

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

                【讨论】:

                  【解决方案11】:

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

                  【讨论】:

                  • 我认为关键是您通常在每个请求的进程中运行 php,而不是每个请求的线程。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-11-21
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多