异常处理和重试 - Amazon Neptune
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

异常处理和重试

在 Neptune 上构建强大的应用程序通常意味着要为意外情况做好准备,尤其是在处理数据库返回的错误时。服务器端异常最常见的响应之一是重试失败的操作。虽然重试逻辑对于弹性系统至关重要,但您需要认识到,并非所有错误都应以相同的方式处理。与其依赖一般的重试行为,不如采用深思熟虑的方法来帮助您构建更可靠、更高效的应用程序。

为什么重试逻辑很重要

重试逻辑是任何分布式应用程序的关键组成部分。网络不稳定、临时资源限制或并发修改冲突等临时问题可能会导致操作失败。在许多情况下,这些故障并不表示永久性问题,可以通过等待并重试来解决。实施可靠的重试策略可以承认分布式系统中环境不完美的现实,从而确保更高的可靠性和连续性,同时减少手动干预的需求。

不分青红皂白地重试的风险

默认情况下,重试每个错误可能会导致一些意想不到的后果:

  • 争用增加 — 当反复重试因高并发而失败的操作时,总体争用可能会变得更糟。这可能会导致交易失败和性能下降的循环。

  • 资源耗尽 — 不分青红皂白的重试可能会在客户端和服务器端消耗额外的系统资源。这可能会导致限制甚至服务降级。

  • 客户端延迟增加-过多的重试可能会导致客户端应用程序出现严重延迟,尤其是在每次重试都涉及等待时间的情况下。这可能会对用户体验和下游流程产生负面影响。

制定实用的重试策略

要构建弹性且高效的应用程序,请制定针对应用程序可能遇到的特定错误条件量身定制的重试策略。以下是一些指导您的方法的注意事项:

  • 识别可重试的错误-并非所有异常都应重试。例如,语法错误、身份验证失败或查询无效不应触发重试。Neptune 提供了错误代码和一般建议,可以安全地重试哪些错误,但您需要实现适合您用例的逻辑。

  • 实现指数退避 — 对于瞬态错误,请使用指数退避策略逐渐增加两次重试之间的等待时间。这有助于缓解争用并降低级联故障的风险。

  • 考虑初始暂停时长 — 如果服务器没有足够的时间释放查询成功所需的资源,那么执行第一次重试的速度太快可能会以同样的错误结束。在适当的情况下延长停顿时间可以减少请求浪费和服务器压力。

  • 给退避增加抖动 — 虽然指数退避是有效的,但如果多个客户端同时失败然后一起重试,它仍然可能导致同步的重试风暴。添加抖动(退避延迟的一个小随机变化)有助于分散重试次数,从而减少所有客户端同时重试并导致负载再次激增的机会。

  • 限制重试次数-设置合理的最大重试次数,以防止无限循环和资源耗尽。

  • 监控和调整-持续监控应用程序的错误率,并根据需要调整重试策略。如果您注意到某项特定操作的重试次数很多,请考虑该操作是否可以优化或序列化。

应用场景示例

正确的重试策略取决于故障的性质、工作负载和您观察到的错误模式。下表总结了一些常见的失败场景以及重试策略注意事项如何适用于每种情况。以下是解释性段落,以提供更多背景信息。

场景

可重试?

退缩和抖动

初始暂停

重试限制

监控和调整

偶尔会有短查询的 CME

短暂的退缩,添加抖动

短(例如,100 毫秒)

关注芝加哥商品交易所利率的上升

在长时间运行的查询上频繁进行 CME

回退时间更长,增加抖动

更长(例如,2 秒)

调查并减少争论

昂贵查询的内存限制

长时间退缩

长(例如,5-10 秒)

优化查询,如果持续查询,则发出警报

中等查询超时

也许

适度退缩,增加抖动

中等(例如,1 秒)

低到中

评估服务器负载和查询设计

场景 1:偶尔会对短查询进行 CME

对于在简短的简单更新期间很少ConcurrentModificationException出现的工作负载,这些错误通常是暂时的,可以安全地重试。在第一次重试之前,请使用短暂的初始暂停(例如 100 毫秒)。此时允许清除任何短暂的锁定。将其与短暂的指数退避和抖动相结合,以避免同步重试。由于重试的成本较低,因此较高的重试限制是合理的。尽管如此,还是要监控芝加哥商品交易所的利率,以捕捉数据中争用增加的任何趋势。

场景 2:对长时间运行的查询进行频繁的 CME

如果您的应用程序经常看到长时间运行 CMEs 的查询,则表明存在更严重的争用。在这种情况下,从较长的初始暂停开始(例如,2 秒),让持有锁的当前查询有足够的时间完成。使用更长的指数退避并添加抖动。限制重试次数,以避免过多的延迟和资源消耗。如果争用仍然存在,请检查您的工作负载是否存在模式,并考虑序列化更新或减少并发以解决根本原因。

场景 3:昂贵查询的内存限制

当在已知的资源密集型查询期间发生基于内存的错误时,重试才有意义,但只有在初始停顿很长时间(例如 5 到 10 秒或更长时间)之后,才能让服务器释放资源。使用长退避策略并设置较低的重试限制,因为如果不更改查询或工作负载,就不太可能解决重复的失败。持续存在的错误应触发警报,并促使人们审查查询的复杂性和资源使用情况。

场景 4:中等查询超时

开销适中的查询超时是一种更加模棱两可的情况。有时,如果超时是由服务器负载或网络状况的临时峰值造成的,则重试可能会成功。从适度的初始暂停(例如 1 秒)开始,让系统有机会恢复。应用适度的退避并添加抖动以避免同步重试。将重试限制保持在低至中等水平,因为重复的超时可能表明查询或服务器容量存在更深层次的问题。监控模式:如果超时频繁,请评估查询是否需要优化,或者 Neptune 集群是否配置不足。

监控和可观测性

监控是任何重试策略的关键部分。有效的可观察性可以帮助您了解重试逻辑的运行情况,并在工作负载或集群配置中的某些内容需要注意时提供早期信号。

MainRequestQueuePendingRequests

该 CloudWatch 指标跟踪海王星输入队列中等待的请求数。值上升表示查询正在备份,这可能是争用过度、资源供应不足或重试风暴的迹象。监控此指标可以帮助您发现重试策略何时导致或加剧了排队问题,并可以提示您在失败升级之前调整方法。

其他 CloudWatch 指标

其他 Neptune 指标(例如CPUUtilizationTotalRequestsPerSecond、和查询延迟)提供了额外的背景信息。例如,CPU 过高, I/O 再加上队列长度的增加,可能表明您的集群过载,或者查询过大或过于频繁。 CloudWatch 可以对这些指标设置@@ 警报,提醒您注意异常行为,并帮助您将错误峰值或重试次数与底层资源限制相关联。

Neptune 状态和查询 APIs

适用于 Gremlin 的 Neptune Status API 及其类似 APIs 的 for OpenCypherSPARQL 提供了集群上接受和运行的查询的实时视图,这对于诊断瓶颈或实时了解重试逻辑的影响非常有用。

通过组合这些监控工具,您可以:

  • 检测何时重试会导致排队和性能下降。

  • 确定何时扩展 Neptune 集群或优化查询。

  • 验证您的重试策略是否能在不掩盖更深层次问题的情况下解决暂时性故障。

  • 收到有关新出现的争用或资源耗尽的预警。

主动监控和警报对于维护 Neptune 的健康部署至关重要,尤其是在应用程序并发性和复杂性不断增长的情况下。