首页 > 解决方案 > 脚本 A 中的 sleep() 会允许脚本 B 运行吗?

问题描述

我有许多每天运行多次的脚本。有些每 5 分钟运行一次,有些则每 10、15、60 分钟运行一次,等等。大多数脚本都在处理大量数据,它们循环遍历并处理每一行。

我主机的cron不允许我决定每个脚本何时启动,我只能选择相隔的分钟数,所以每5分钟运行一次的脚本,在00,05,10,15...运行的脚本和运行的脚本每 10 分钟运行在 00,10,20,30... 等。

这意味着很多脚本从 00 开始运行。

除了服务器也被普通用户使用,这些用户通常只需要做一些不应该花费很多时间的事情之外,这并不是一个真正的问题。但是,如果他们碰巧在许多脚本正在运行时这样做,那么一切都会变慢,而且他们甚至无法在不等待很长时间的情况下完成那些简单的事情。

我在某处读到睡眠功能会阻止 CPU 处理数据并允许运行较小的任务。你知道是不是这样吗?如果我在这些脚本中的每个循环之后插入一个 sleep(1),这会提高执行小任务的单个用户所看到的性能,即允许他们跳过该行吗?

每 5 分钟运行一次的示例脚本 A

foreach ($a_hundred_things as $one_thing) {
  do_this($one_thing);
  // would adding sleep(1); here improve performance?
}

用户单击按钮时运行的脚本 B

do_this_thing_that_only_takes_a_minute();

目前,如果像脚本 A(以及许多其他类似的脚本)正在运行,用户有时需要等待很长时间(几分钟)才能运行脚本 B。我希望 B 能够以某种方式获得优先权,因为这是迫不及待的事情,而自动脚本可以承受延迟。

在脚本 A(以及同时运行的所有其他类似脚本)中添加 sleep(1) 会提高性能吗?我知道我可以尝试对其进行测试,但是涉及到很多脚本,而且这似乎并非每次都会发生。

标签: phpperformancecpusleep

解决方案


首先,让您指定要休眠usleep()多少微秒,并且是高级功能。

以下是杂牌,但可以在您实施更好的解决方案时帮助减轻打击:

  1. 在 cron 的开头插入几秒钟的随机等待,这样它们就不会同时启动。这可以防止您的机器每 15 分钟就被完全撞击,同时一切都在一次初始化。

    usleep(mt_rand(0,10000000));
    
  2. 贫民区节流。测量执行一次循环迭代所需的时间,然后休眠那么长时间。您有效地将性能降低了一半。

    while($condition) {
      $start = microtime(true);
      // do work
      usleep( (microtime(true) - $start) * 1000000) );
    }
    

您应该使用的实际解决方案,请注意,这些解决方案并不相互排斥:

  1. 将定期/异步任务转移到一台或多台其他机器。没有理由通过与用户请求没有直接关系的工作对面向用户的基础架构的性能产生负面影响。

  2. 对异步任务使用队列/工作者模型,并且只使用 cron 定期提交作业进行处理。这大致相当于:

    1. 创建一个通用的工作进程。
    2. 设置任务队列。【我推荐兼容AMQP的队列系统,个人更喜欢RabbitMQ】
    3. 启动一个或多个工作进程,像 Supervisord 这样的东西可以很容易地保持一小部分工作人员的运行。

哎呀!你已经实现了这两个?这就是所谓的“水平扩展”以及我们在 2020 年构建现代应用程序的方式。现在您可以按需启动机器和流程,甚至可以自动启动。抱歉给您带来方便。:P


推荐阅读