绝不会错过任何 HTTP 帖子

绝不会错过任何 HTTP 帖子

我有一个 Web 服务,它连接了几个“机器”客户端,偶尔会发送 HTTP 数据。该服务的本质是,我不能允许服务丢失任何传入请求。但是我确实遇到过这种情况:偶尔我会收到来自数据库后端或类似设备的错误,导致错误并丢失帖子。(但是响应并不那么重要)。

是否有关于如何处理此类错误的最佳实践文档/架构描述。我正在考虑将传入请求排队并稍后再尝试,或者将其转发到 Webfarm 中的另一个 Web 服务器。

我目前在 AWS 中运行 IIS7.5 Web 应用程序,后端为 RDS/MySQL 数据库。所有内容均已负载平衡并以多可用区模式运行。我的想法是将任何麻烦的请求放入 SQS 并定期处理该队列,但我想已经对这一领域进行了很多思考,如果我自己动手,可能会遇到一些陷阱。

答案1

首先,如果您确实无法处理哪怕是少量的停机时间(例如发生故障时),那么您应该在客户端应用程序中实现重试逻辑。

如果对这些请求的响应不是时间敏感的(例如,它是一个日志,只要记录了日志,那么日志是否立即传送并不重要),那么我肯定会考虑使用基于队列的架构。

新加坡优质服务是 AWS 上队列的明显选择,但请记住:

  • 虽然它是分布式且高度可用的,但个别节点确实会不时出现故障。如果您碰巧遇到一个无效的 SQS 节点,您仍然需要在客户端中重试逻辑。
  • SQS 仅允许“至少一次”传递,因此您可能会收到一条消息不止一次。根据我的经验,这种情况很少见,大概最常发生在节点发生故障时。

还要确保您的基础设施在可用区域之间复制,最好在区域之间复制。例如,当向主区域提交失败时,您的客户端可以尝试在另一个区域使用 SQS。

答案2

实现一个永远不会失败的 Web 服务(即使是单个 HTTP 请求)非常困难。而且可能不值得付出努力。即使您设法让服务处理每个 POST 请求并发送成功的回复,客户端也可能会遇到其他问题:

  • 客户端和服务器之间的某些中间件会跟踪连接并丢弃其状态。
  • 短时间内出现大量数据包丢失会导致客户端的 TCP 堆栈连接超时。
  • 客户端应用程序级别的连接超时。

客户端必须以与 5xx 错误代码完全相同的方式处理所有这些错误,如下所示:

  • 不要假设请求是否被处理。如果请求没有被设计为幂等的,客户端必须执行一个稍微复杂的恢复来判断是否需要重新提交请求。
  • 客户端必须使用指数退避算法重试,以防止服务在高负载下崩溃。

相关内容