我有一个Spring应用程序,今天使用@Async
方法来处理一些非必要但信息丰富的内容。它很棒。
我想将一些新处理移到应用程序的这个角落,但我不完全理解如果它通过AWS关闭,它在运行的ec2实例中会发生什么。
此应用程序在AWS中的Tomcat 8上运行,作为Autoscaling组的一部分。我们经常部署,并且可以大量扩展和缩小,因此机器终止是常规的。我知道这可能会导致某些线程在流中停止,这是可以接受的。
现有用例:"通过Slack向中层管理人员报告最后一小时的销售情况。"
我知道机器关机可能导致Slack消息没有发布,这没关系。它只是中层管理人员。
新用例:"每天凌晨5点通过电子邮件向高级管理层报告最后一天的销售情况。"
如果此报告需要很长时间才能运行,则如果电缆被拉扯,运行它的线程更有可能停止运行。
我知道如何防范这种情况并使事情变成原子性的#34;通过Redis等,但这不会扩展到连续失败或任务持续时间最终超过ec2生命周期,我想更深入地了解ec2实例"关闭"命令通过@Async
方法调用影响当前正在运行代码的正在运行的jvm线程。
我不想在Lambda或其他任何带外运行这些东西,因为我们的域位于此代码库中并经常更新。
我已经搜索了一下这个主题,几乎所有结果都会产生他们的应用容器的主题而不是在这种情况下关闭,这与我正在寻找的信息相反。
谢谢!
-neil
答案 0 :(得分:2)
这里有几点需要注意:
直接回答您的问题:
当aws自动缩放组成员被销毁时会发生什么 还有出色的Spring异步线程吗?
线程获得InterruptedException。
您描述的场景并不适合自动缩放实例。那些是为处理交通而设计的。您的场景更多地是关于作业处理。专用(可能是预定的)实例(车队)更适合这种情况。如果您需要运行其中许多,可以安排Spot实例以降低成本。如果您通常在流量处理机器上运行作业,听起来您正在混合应用程序中的问题,更好地拆分它们。
在实例中,我运行的应用程序对作业进行了一些状态管理。你可以自己编写,使用像DynamoDB这样的持久存储(Elasticache很好但是如果失败了怎么办?),或者让其他工具为你做这些(比如Oozie,Chronos / Airflow,取决于你喜欢什么?式语言)。
如果自己实施,每个报告间隔都会有一个记录(让我们说一天)。状态机将是:Not Running
(与缺席相同),Running
,Failed
,Done
。除Not Running
之外的所有时间戳都将具有上次更新时间戳,该时间戳将针对正在运行的作业定期更新。还有一个实例/进程/线程标识符,谁拥有正在运行的作业。如果作业被标记为正在运行,但更新缺失超过X个时间间隔,则可以将前一个运行器声明为失败,并且观察到此情况的下一个实例可以获得此作业的所有权(更新所有者)。
答案 1 :(得分:1)
一种听起来很苛刻的答案,但假设关键@Async
处理可能发生在任何一个框中(或发生在所有框中),那么你可以让它在启动关键处理时让实例调用aws CLI完成后再打电话给它?它应该能够以这种方式启用实例保护。
使用以下update-auto-scaling-group命令为指定的Auto Scaling组启用实例保护:
aws autoscaling set-instance-protection --instance-ids i-5f2e8a0d --auto-scaling-group-name my-asg --protected-from-scale-in
文件中的其他地方:
如果在缩放期间保护Auto Scaling组中的所有实例免于终止并且发生缩放事件,则Auto Scaling会减少所需的容量。但是,Auto Scaling无法终止所需数量的实例,直到其实例保护设置被禁用。
实例保护不会通过Amazon EC2控制台,terminate-instances命令或TerminateInstances API保护Auto Scaling实例免于手动终止。如果Auto Scaling实例的运行状况检查失败并且必须更换,则实例保护不会保护Auto Scaling实例不被终止。此外,实例保护不会保护Auto Scaling组中的Spot实例免受中断。
或者,如果只需要一个盒子运行它,那么应该可以将一个专用实例保护为 processing 框,你只需要确保该实例是一个这是你的关键异步处理。