水平缩放和cron作业

时间:2017-02-22 23:29:29

标签: amazon symfony

我最近被迫将我的应用程序移动到亚马逊并使用自动缩放,我偶然发现了cron作业和自动缩放的问题。

我有一个每15分钟运行一次的cron作业,它会检查是否应该收取订阅费用,查询会选择所有已过期的订阅,并尝试向其收费。它会在处理后更改其状态,但它们会在批处理中获取,并且该过程需要1-3分钟。

如果我有多个具有相同cron作业的实例,则可能会同时触发并多次收取订阅费用。这实际上已经发生了一次。

这里最好的方法是什么?以某种方式锁定表或?

我正在使用Amazon弹性beanstalk和symfony3。

2 个答案:

答案 0 :(得分:1)

至少你可以使用专用微实例进行订阅收费(当然不是自动扩展),只需使用cron作业。最简单的方法,但最安全(显然,如果您从前端服务器移动订阅处理逻辑,这可能是安全的,可能会被攻击到VPC子网后面的服务器,而该服务器不能从全球网络获得)。

但如果你不想要,你仍然可以使用另一种方法。您提到使用BeanstalkBeanstalk允许使用延迟的工作。

所以可能的方法是:

1)当您创建订阅时,您可以计算何时应该收费,然后将计算延迟的作业推送到Beanstalk管。

2)然后,工人按时获得工作(订阅)。只有一个工作人员才能完成特定工作,因此如果您使用自动扩展工作,它将起作用。

3)在工作人员中,您检查订阅(可能是删除或非活动等),如果准备充电,只需运行代码进行充电。然后计算下一个充电时间并将新的延迟作业(带有订阅)推送到队列。

BeanstalkSymfony bundlepowerful PHP library

答案 1 :(得分:0)

您可以使作业仅在一个实例上运行,即使您的功能-收费订阅仅在其中一个实例上运行。 您可以使用AWS api来获取所有实例,然后将这些实例与当前正在运行的实例进行匹配。

ec2 = Aws::EC2::Resource.new(region: 'region',
credentials: Aws::Credentials.new(IAM_KEY', 'IAM_SECRET')

metadata_endpoint = 'http://169.254.169.254/latest/meta-data/'

current_server_id = Net :: HTTP.get(URI.parse(metadata_endpoint +'instance-id'))

instances = []
ec2.instances.each do |i|
  if (i.state.name == 'running')
   instances << i.id
 end

结束

如果(instances.first == current_server_id)

{
  your functionality
}