检查S3文件是否已被修改
如何使用shell脚本检查Amazon S3文件(小型.xml文件)是否已被修改。 我目前使用curl
来检查每10秒钟,但它正在做出很多GET请求。
curl "s3.aws.amazon.com/bucket/file.xml"
if cmp "file.xml" "current.xml"
then
echo "no change"
else
echo "file changed"
cp "file.xml" "current.xml"
fi
sleep(10s)
有没有更好的方法来每10秒检查一次,以减少GET请求的数量? (这是建立在rails应用程序之上的,所以我可以在rails中构建一个处理程序?)
首先让我先告诉你一些关于S3的事实。 你可能知道这一点,但如果你不知道,你可能会发现你当前的代码可能会有一些“意想不到的”行为。
S3和“最终一致性”
S3为被覆盖的对象提供“最终一致性”。 从S3 FAQ中 ,您可以:
问:Amazon S3使用什么数据一致性模型?
所有区域中的Amazon S3存储桶为新对象的PUTS提供读写后一致性,并为覆盖PUTS和DELETES提供最终一致性 。
覆盖的最终一致性意味着,无论何时更新对象(即每当你的小XML文件被覆盖时),检索文件的客户端都可以看到新版本,或者他们可能会看到旧版本。 多长时间? 时间不确定。 它通常在不到10秒的时间内达到一致性,但是您必须假设最终需要超过10秒才能实现一致性。 更有趣的是(可悲的是?),即使在成功检索新版本之后,客户端可能会在稍后收到旧版本。
您可以确定的一件事是:如果客户端开始下载一个文件版本,它会下载整个版本(换句话说,您不可能收到例如XML文件的前半部分为旧版本和下半年作为新版本)。
考虑到这一点,请注意,您的脚本可能无法在10秒内识别出更改:即使在更改后,您也可以发出多个请求,直到您的脚本下载更改后的版本。 即使如此,在检测到更改后,(不幸的是)完全有可能下一个请求会下载以前的(!)版本,并在您的代码中触发另一个“更改”,然后下一个请求会提供当前版本,并在你的代码中触发另一个“变化”!
如果您确信S3提供了最终一致性,那么您可以通过一种方法来改进您的系统。
想法1:S3事件通知+ SNS
你提到你想过使用SNS。 这绝对是一个有趣的方法: 您可以启用S3事件通知 ,然后在文件更新时通过SNS获取通知。
你如何得到通知? 您需要创建订阅,并且在这里您有几个选项。
Idea 1.1:S3事件通知+ SNS +“网络应用”
如果您有一个“Web应用程序”,即任何运行在可公开访问的HTTP端点中的任何东西,您都可以创建一个HTTP订阅者,这样SNS就会在发生通知时通知您的服务器。 在您的情况下,这可能或可能不可行或不可取
想法2:S3事件通知+ SQS
您可以在SQS中创建消息队列,并让S3直接将通知传递给队列。 这也可以作为S3事件通知+ SNS + SQS,因为您可以添加队列作为SNS主题的订阅者(其优点是,如果您稍后需要添加功能,则可以添加更多队列并订阅它们到同一主题,因此获得通知的“多个副本”)。
要检索通知,您需要打电话给SQS。 你仍然需要轮询 - 也就是说,有一个循环并在SQS上调用GET(与S3 GET相比,其成本大致相同,也可能稍微多一点取决于区域)。 略有不同的是,您可以减少总请求的数量 - SQS支持长达20秒的轮询请求 :您在SQS上进行GET调用,并且如果没有消息,则SQS将请求保持为up如果消息到达,则立即返回;如果在20秒内没有消息可用,则返回空响应。 所以,你每20秒只发送一次GET,以获得比目前更快的通知。 你可能会减少你获得的数量(S3每10秒一次,而SQS每20秒一次)。
另外 - 您可以选择使用一个SQS队列将所有更改聚合到所有XML文件或多个SQS队列(每个XML文件一个)。 通过一个队列,您可以大大减少GET请求的总数。 每个XML文件都有一个队列,这就是您可以将GET请求的数量与现在相比减少一半的时间。
想法3:S3事件通知+ AWS Lambda
您也可以为此使用Lambda函数。 这可能需要在您的环境中进行一些更改 - 您不会使用Shell脚本进行轮询,但可以将S3配置为为您响应某个事件(如XML文件的更新)而调用Lambda函数。 你可以用Java,Javascript或Python编写你的代码(有些人设计了一些“黑客”来使用其他语言,包括Bash)。
这样做的好处在于,不再需要进行轮询,而且不必维护Web服务器(如“1.1概念”)。 只要有变化,您的代码就会“简单运行”。
请注意,无论您使用这些创意中的哪一个, 您仍然需要处理最终的一致性 。 换句话说,你会知道PUT / POST发生了,但是一旦你的代码发送了一个GET,你仍然可以收到旧版本...
想法4:改用DynamoDB
如果您有能力对系统进行更多结构性更改,则可以考虑使用DynamoDB执行此任务。
我建议这样做的原因是因为DynamoDB支持强大的一致性,即使是更新。 请注意,这不是默认设置 - 默认情况下,DynamoDB以最终一致性模式运行,但“检索”操作(例如GetItem)支持完全一致的读取。
另外,DynamoDB具有我们称之为“DynamoDB Streams”的功能,该功能允许您获取对表中任何(或全部)项目所做的更改。 这些通知可以被轮询,或者甚至可以与Lambda函数一起使用,每当发生更改时都会自动调用这些通知! 这一点以及DynamoDB的强大一致性可以帮助您解决问题。
在DynamoDB中,保持记录很小通常是一种很好的做法。 您在您的评论中提到您的XML文件大约为2kB--我认为可以认为它足够小,以便它适合DynamoDB! (推理:DynamoDB读取通常是以4kB的倍数来计算的;因此要充分读取1个XML文件,您只需要读取1次;另外,根据您的操作方式,例如使用Query操作而不是GetItem操作,您可能可以从DynamoDB中读取2个XML文件,只需要1次读取操作)。
一些参考:
http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html
http://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html
http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html
上一篇: Check if S3 file has been modified
下一篇: ReactNative ListView setting initial scroll position after data loaded