【问题标题】:Lots of PHP processes running at the same time大量 PHP 进程同时运行
【发布时间】:2015-10-22 13:38:57
【问题描述】:

要求

我有一个网络应用程序,它允许用户安排一些社交媒体任务,例如在 Facebook 或 Twitter 上发帖。

每个用户都可以让应用随时(14:00、15:11、17:54...)在他的社交媒体帐户上发布。

除此之外,我还需要每天为每个用户完成其他任务,例如获取他们的关注者/朋友或在 Twitter 上取消关注他们的人。

情况

到目前为止,我已经为每个任务创建了一个文件(post.php、getFollowers.php、analytics.php...)。例如:

post.php

我为此脚本创建了一个 cron 作业,它每分钟检查是否必须发布某些帖子。假设我们运行脚本,此时它找到了三个想要发推文的用户,它将使用 foreach 循环迭代用户并在每个帐户中发帖。

...其他脚本也这样做:获取每个想要做某事的用户,创建一个队列并对其进行迭代。

问题

  1. 发布任务需要按时完成。
  2. 获取关注者之类的长任务需要每天运行。

(1) Twitter 和 Facebook 发帖需要 30-40 秒,所以如果有 5 个用户想在 14:00 发帖,那么 3、4 和 5 就晚了。

(2) 获得一个用户的一些追随者需要 40-60 秒,因此只有 1000 个用户,脚本将花费 11-16 小时,这绝对是不可扩展的。我应该能够在 2-3 小时内完成这项任务。

解决方案?

我认为我可以通过分离用户任务并为每个用户执行一个进程来解决这两个问题。

这是一个正确且可扩展的解决方案吗?您将如何以可扩展的方式解决这些问题?

提前致谢。

【问题讨论】:

  • 那没有用。 exec() 阻塞,直到您正在执行的任何操作完成。您必须将该工作放在后台,例如exec('somejob &'),然后引发了一系列其他问题。
  • @MarcB 谢谢马克。我不知道。有什么建议吗?
  • 你的架构是什么样的?你有工人等级吗?这个article 可能很有趣。
  • 可能值得研究 AWS 或其他云服务以卸载大量进程而不必担心您的服务器性能
  • @FrancisEytanDortort 我在 Hostgator 上有一个简单的共享服务器。有趣的文章。但是他们如何使用一个脚本按时发布每个用户的帖子呢?

标签: php cron


【解决方案1】:

使用队列和工作器系统。

队列,例如:Amazon SQS:

  1. 用户将事情安排在 X 时间发生。
  2. cron 定期运行,查找需要运行的作业。
  3. cron 脚本将作业弹出到队列中。

工人:

  1. 向队列询问作业
  2. 做这项工作
  3. 转到 1

诀窍是你有一个队列,然后有尽可能多的工作进程/服务器来防止队列持续增长。

【讨论】:

  • 感谢您的回答。通过这种方式,我将在 Amazon SQS 上安排任务,它会调用我的服务器上的工作进程,这些进程将为每个用户完成这项工作。我理解的很好吗?
  • 几乎,你需要启动工人,他们要求排队工作。好处是您可以根据需要启动任意多个,并随时停止它们。真正的“多云”解决方案是根据任何给定时间的需求自动启动/关闭旋转工作进程/服务器。
【解决方案2】:

使用托管的分布式计划任务服务,例如 AWS Elastic Beanstalk Worker TierIronWorker

使用 AWS EB,您可以在项目中包含一个 cron.yaml 文件,其中包含如下配置:

version: 1
cron:
 - name: "post"
   url: "/post"
   schedule: "* * * * *"

这将触发每分钟对http://localhost/post 的 POST 请求。

我还建议计划任务本身发送帖子,而是触发其他多个任务这样做。使用 AWS EB,您可以使用 AWS SDK for PHP

use Aws\Common\Aws;

$aws = Aws::factory('/path/to/my_config.json');
$client = $aws->get('Sqs');

$client->sendMessage(array(
    'QueueUrl'     => $queueUrl,
    'MessageBody'  => json_encode($post),
    'DelaySeconds' => $delay,
));

对于正文中包含 JSON 编码数据的每条消息,这将触发对您为 Worker Tier 配置的 URL(即http://localhost/worker)的 POST 请求。

这种方法可以让您更好地扩展同时发送的帖子数量。

【讨论】:

  • 感谢您的回答。所以...对于多个任务,我将收到对使用 AWS 开发工具包的文件的请求,它将处理发布信息并在队列中安排一条消息。然后,该队列会按时向我的服务器发送一个请求以及该信息。我理解的很好吗?
  • 是的。例如,计划任务会寻找下一分钟发布的帖子,然后在队列中为每个帖子创建一条消息,延迟为 60 秒。然后,每条消息将在给定的延迟后触发自己的 http 请求。您可以将延迟增加到最多 15 分钟。长延迟的好处是你可以使用队列大小来触发增加工作实例的数量。
  • 谢谢弗朗西斯,很好的解释。我必须雇用aws.amazon.com/sqs,不是吗?你知道我是否可以在 Hostgator 共享服务器中使用 cron.yaml 吗?我想如果某个用户删除了帖子,我将能够删除该消息。再次感谢
  • 我的解释是用于 AWS Elastic Beanstalk。这意味着,至少 Worker Tier 必须托管在 AWS 上。 (顺便说一句,第一年的一些资源是free。)你可以阅读服务here,有一个walkthrough on deploying an appphp specific details
猜你喜欢
  • 2014-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多