6

我正在构建一个后端模块(用 PHP 编写),它将用于监视在 [Exactly] 300 seconds (5 minutes) 内没有活动的私人聊天室。如果是,脚本将更新数据库(将最大用户设置为某个数字,以及其他内容)。我正在通过 now() 和发送的最后一条消息的时间差来监控空闲时间的跨度。


我所做的:设置一个 cron 作业,它将每分钟或 60 秒运行一次(通过 php-cli)我的监控脚本。监控脚本内部:

$expire_time = time() + 60;

//this loop will run for 60 seconds
while(time() < $expire_time)
{
  $idle_time = get_all_chatrooms_idle_time();
  foreach($idle_time as $s_time)
  {
    if($s_time >= 300)
    {
      update_changes();
    }
  }
  usleep(500000);
}

在 300 秒空闲时间后立即设置最​​大用户数的条件无法讨价还价。所以我不能真正遵循这样的建议:“避免做任何事情,直到有事情真正要求它”,即使它很有意义。

原因?活跃和不活跃聊天室的数据需要是实时的,因为它也会显示在仪表板上。聊天室版主的报酬取决于此。


为什么不在每次仪表板负载时检查它们?我很抱歉,但仍然不可能。

检查需要在服务器端进行,仪表板使用 ajax 更新自身,每秒轮询一次。

当我将监控代码附加到我的 ajax 调用所请求的页面时,我认为它比我当前的实现更占用资源(如果我错了,请纠正我)

让我粗略估计一下用户数量,这样你就可以想象我们得到的负载/流量:

  • 包括版主在内的聊天人数:~800
  • 聊天室数量:~250
  • (x) 聊天室版主人数:~50
  • (x) 我的老板和他的员工:

(x) - 可以查看仪表板


有没有更好的办法?我做对了吗?

4

3 回答 3

2

这个循环是一个矫枉过正。即使在中等服务器上,它也可能每分钟运行数千次,即使对于实时应用程序,它也会产生高 CPU 使用率。添加一个计数器,并查看迭代计数。我认为这会产生比处理每个 AJAX 请求更多的负载。

首先,确定您需要信息的粒度。假设您选择有 3 秒的粒度(例如每 3 秒扫描一次数据库)——这个数字可能对您来说太高了,但它说明您不会损失太多。随着 AJAX 每秒拉动,您可能会看到一些应该不断向上爬的计数器爬回一两次。(你是否真的会看到这样的事情取决于你的柜台的性质。)

如果您的计数器基于秒范围内的数据(例如显示经过的秒数总和,或基于 $/sec 的金额),那么第二次 AJAX 拉取将不会提供连续计数器。(它有时会错过一秒钟或两次更新到那一秒钟;出于网络原因)。

无论选择的粒度如何,您的最终统计信息都没有问题,因为它们是基于绝对时间戳的——无论它们被评估多晚。

如果使用第二次 AJAX 轮询来实现平滑计数器,那么您可以做得比这更好:计数应该在客户端运行(例如发送具有第二次增量的值:revenue: <span data-inc="25">14432</span>并使用 JS 进行计数)。唯一实现 AJAX 来监视停止/重置计数器的条件。然后您只需要确定通知可能延迟多长时间(例如 10 秒)然后计数器将过度滚动到最大值。10s 回落到预期值。在这种情况下,您不应该更频繁地运行 DB 清理(例如,间隔的一半)。例如,这允许在您的周期中进行 3 秒的睡眠,从而大大减少负载。

如果您可以轻松地选择将每个聊天室的过期时间戳添加到数据库(记录中的或固定的),并使用可以加快读取速度的索引(并另外允许每个房间的过期规则)。

于 2012-12-07T07:37:40.817 回答
1
#!/usr/bin/php
<?php

if( file_exists('/tmp/chatrooms_cron.lock') ) {
   die( 'There is already a script running.' );
}

file_put_contents( '/tmp/chatrooms_cron.lock', 1 ); // Storing pid would be better 

// Run loop forever
while( true )
{
  $idle_time = get_all_chatrooms_idle_time();

  foreach($idle_time as $s_time)
  {
    if($s_time >= 300)
    {
      update_changes();
    }
  }

  sleep( 60 );
}

node.js 的提示(使用 socket.io):

我在工作中一直在使用 node.js,非常棒!将是实时的,并且可以与低至 ie5/ie6 的浏览器一起使用。这可以在 node.js 内部完成。

setInterval( function() {
   // Fetch and update peers
}, 300000 );
于 2012-12-07T07:46:27.340 回答
1

根据评论,我建议使用诸如node.js之类的技术,它是一个偶数驱动的 I/O 异步平台来构建应用程序。如果聊天室是一个外部应用程序,您可以轻松地打开一个套接字并监听聊天室、记录它、检查用户的活动并监听特定事件。

于 2012-12-07T07:37:45.643 回答