【问题标题】:Long Polling with Ajax and PHP - Apache freezes使用 Ajax 和 PHP 进行长轮询 - Apache 冻结
【发布时间】:2013-04-11 10:25:37
【问题描述】:

我们尝试在我们公司的 ERP 中实施基于长轮询的通知服务。类似于 Facebook 通知。

使用的技术:

  • 在循环的每次迭代中,timeout 设置为 60 秒和 1 秒 sleep 的 PHP。
  • 用于 AJAX 处理的 jQuery。
  • Apache 作为 Web 服务器。

经过近一个月的编码,我们进入了生产阶段。部署后几分钟,我们不得不回滚所有内容。事实证明,我们的服务器(8 核)无法处理来自 20 名员工的长请求,每个员工使用约 5 个浏览器选项卡。 例如:用户使用我们的 ERP 打开了 3 个选项卡,每个选项卡上都有一个长轮询 AJAX。不可能打开第 4 个选项卡 - 它会挂起,直到前 3 个选项卡中的一个被杀死(因此 AJAX 停止)。

'Apache 限制',我们想。所以我们去谷歌搜索。我找到了一些关于 Apache 的 MPM 模块和配置的信息,所以我试了一下。我们的服务器使用prefork MPM,正如apachectl -l 向我们展示的那样。所以我在配置中更改了几行,看起来像这样:

<IfModule mpm_prefork_module>
    StartServers          1
    MinSpareServers       16
    MaxSpareServers      32
    ServerLimit          50%
    MaxClients          150
    MaxClients           50%
    MaxRequestsPerChild   0
</IfModule>

有趣的是,它可以在我的本地机器上使用类似的配置。在服务器上,看起来 Apache 忽略了配置,因为 MinSpareServers 设置为 16,重启后它会启动 8。谁不知道该怎么办。

【问题讨论】:

  • 虽然不太可能,但在各种浏览器上都实现了limit on maximum persistent connection per server。您可能想测试第四个选项卡是否会挂起任何数量的员工连接。
  • 不要休眠锁定 apache/php 线程的页面。您需要增加您的 apache 工作人员等并将所有这些废话线程化。在我的 CRM 平台中,我使用一个简单的文本文件查找每个用户 ID。如果差异> 60,则上次检查的时间戳与现在的时间戳,然后进行轮询,否则什么也不做。将脚本设置为每秒运行一次。
  • 在 python 上尝试使用 websocks。

标签: php ajax apache long-polling


【解决方案1】:

上一篇文章的第一条评论中的路人给了我一个很好的方向来检查我们是否达到了最大浏览器连接到一个服务器。

事实证明,每个浏览器都有这些限制,您无法更改它们(据我所知)。 我们制定了一种解决方法以使其正常工作。

假设我从

获取AJAX 数据
http://domain.com/ajax

为避免达到最大浏览器连接数,每个长轮询AJAX 都会连接到随机子域,例如:

http://31289.domain.com/ajax
http://43289.domain.com/ajax

等等。 DNS服务器上有一个通配符从*.domain.com指向domain.com,子域是唯一的随机数,由JS在每个选项卡上生成。

欲了解更多信息,请查看this thread

AJAX Same Origin Security 也存在一些问题,但我们设法解决了问题,在JSPHP 两侧都使用了适当的标题。

如果您想了解有关标头的更多信息,请查看here on StackOverflowhere on Mozilla Developer's page。谢谢!

【讨论】:

  • 你是说除了浏览器对连接的限制之外,长轮询在你的 apache 服务器上工作正常吗?
【解决方案2】:

我已经成功实现了长轮询的 LAMP 设置。有两件事要记住,linux 的 php 内部执行时钟不会被“usleep()”函数改变或增加。因此,只有在获取数据所需时间比正常时间更长的罕见边缘情况下,或者可能用于 Windows 设置时,才需要设置最大执行时间。此外,考虑到长时间轮询,一旦超过 20 秒,您很容易发生浏览器超时。

其次,您需要验证您的会话没有锁定(如果正在使用会话)。

Apache 真的不应该对您想要做的事情有任何问题。不过,我承认像 nginx 这样的网络服务器或特定于 ajax 的网络服务器可以更好地处理并发连接。如果您可以发布 ajax 处理程序的代码,我们或许能够找出问题所在。

使用子域,或者正如其他线程所建议的那样——不同端口上的多个网络服务器,请记住您可能会遇到 JavaScript 域安全问题。

我说,在遇到问题并用尽所有其他选项之前,不要更改 apache 配置;小心 PHP 会话,并确保 AJAX 正在等待响应,然后再发送另一个请求;)

【讨论】:

  • 在开发通知服务时,我尝试了很多东西。我也做了类似你提议的事情。当您尝试一次支持数百个(或更多)连接时,整个想法都会失败 - 您只会杀死服务器。不过,我找到了一个更好的解决方案——使用 Socket.io 作为连接协议的 Node.js。我知道学习新技术需要一些时间,但这是值得的。这非常值得,我花了半年时间在我的计算机科学硕士论文中描述它:) 你应该试试!玩得开心!
猜你喜欢
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
  • 2013-10-01
  • 2016-08-14
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多