5

我最近被迫将我的应用程序转移到亚马逊并使用自动扩展,我偶然发现了一个与 cron 作业和自动扩展有关的问题。

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

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

这里最好的方法是什么?不知何故锁定表或?

我正在使用 Amazon elastic beanstalk 和 symfony3。

4

2 回答 2

0

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

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

所以可能的方法是:

1)创建订阅时,可以计算出什么时候应该收费,然后将计算好的延迟的作业推送到Beanstalktube。

2)然后,工人按时得到工作(订阅)。只有一名工作人员会获得特定的工作,因此如果您使用自动缩放,它将起作用。

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

Beanstalk拥有Symfony 包强大的 PHP 库

于 2017-02-23T09:21:08.037 回答
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
end

if (instances.first == current_server_id )
{
  your functionality
}
于 2018-12-21T06:36:55.407 回答