【问题标题】:How best for an API running on a web server to check its public availability / status在 Web 服务器上运行的 API 如何最好地检查其公共可用性/状态
【发布时间】:2017-04-23 05:24:41
【问题描述】:

我有一个处理最终用户注册的 AWS 服务器/它运行一个 EC2 linux 实例,该实例通过 Apache 和 Python 为我们的 API 提供服务,并连接到运行 mysql 的单独 Amazon RDS 实例上的数据。

为了远程管理系统,我在 mysql 表中设置了状态来控制注册 API 对公共用户的可用性,以及我们的 Python API 的日志记录级别,它可以引用多达 5 个并发管理首选项(即不是一个单一的“日志级别”)

由于我们的 API 提供了近两打不同的功能,我们需要在访问任何单个功能之前检查系统的可用性状态。这意味着该表中有一条 SQL Select 语句(只有一条记录),但对于用户事务的每个会话,可能涉及六次 API 调用。我们需要检查可用性状态是否发生了变化,因此用户不会启动 API 调用,并且在过程中间让数据库变得不可用。日志记录首选项也是如此。

API 调用将服务器的可用性和估计的停机时间返回给调用程序(不是 Web 浏览器界面),它可以优雅地处理这种情况。

这是处理此问题的普遍接受的方法吗?如果我过度轮询状态表,我应该关心吗?当 Python 获取数据时,我是否应该使用我的状态表设置 mysql,以使我的持续检查更有效(例如缓存?)?

我应该注意,我们可能有数千个同时发出 API 请求的用户,而不是数万或数百万。

【问题讨论】:

  • SO 不适合讨论分布式系统架构,SO 是关于编程的。此外,它不是编解码器编写服务,因此我们希望请求用户提供他已经编写的代码来解决问题。
  • 克劳斯,我的错——我认为因为这与mysql有关,我做了编程,mysql是这里的一个主题,询问使用我描述的方法的效率适合与其他SO问题。在上面的例子中,它是一个单独的 Select 语句,所以没有任何东西可以提供任何精通 mysql 语法的人都无法想象的东西。我会重新考虑、重写或撤回这个问题,但即使是 SO 提出的“相关”问题(有数百或数千张选票)也是同类问题。

标签: python mysql rest amazon-web-services asp.net-web-api


【解决方案1】:

在这里,您的策略似乎偏离了轨道。

轮询状态表不应成为主要热点。在事务外部查询具有适当索引的小表是一种轻量级操作。使用适当配置的服务器,这样的查询应该完全在内存中完成,不需要磁盘访问。

但这并不意味着这是一个完全可行的策略。

我们需要检查可用性状态是否发生了变化,因此用户不会启动 API 调用,并且在处理过程中数据库变得不可用。

这将被证明是不可能的。您需要时间旅行能力才能使此策略成功。

考虑一下:您的方法不会检测到在进程中间变得不可用的数据库。只会在开始时检测到可用性不足。无论如何,这很容易检测到——一旦你尝试做某事,你就会意识到这一点。

设置适当的超时。 MySQL 客户端库应该支持连接超时,以及如果查询运行时间超过可接受的时间或网络中断导致连接在查询中丢失,超时将导致您的应用程序看到错误。我不知道这是否存在或者它在 Python 中被称为什么,但在 C 客户端库中,这是 MYSQL_OPT_READ_TIMEOUT,并且对于防止挂起非常方便,无论出于何种原因您都没有得到响应数据库在可接受的时间段内。

使用数据库事务,以便处理请求失败不会导致数据库发生净变化。如果应用程序和数据库之间的连接丢失,MySQL 事务会隐式回滚。

实施错误处理和恢复(写入您的代码)可能是一种更可行的方法,而不是在服务不可用时尝试阻止您的代码运行更有可能是一个好的设计,因为没有检查间隔小到足以完全避免数据库在请求的“中间”变得不可用。

在任何情况下,对每个请求都轮询数据库表似乎是错误的方法,更不用说当服务本身可能是健康的但未能成功时,健康状态表的服务器上的中断会使您的服务不必要地失败。证明这一点。

另一方面,我不知道您的架构,但假设您的前端涉及 Amazon Application Load Balancer 或 HAProxy 之类的东西,针对 API 服务端点的运行状况检查实际上可以执行测试。如果您将检查间隔配置为 10 秒,并且向检查端点发出请求(例如 GET /health-check)实际上验证了必要组件(例如数据库访问)的端到端可用性,那么 API 服务当出现问题时,可以有效地使自己脱机。它保持离线状态,直到它再次开始返回成功。

这里的优点是您参与健康检查的工作负载是一致的 - 每 10 秒发生一次,随着提供服务的节点数量而增加,但不会随着实际请求流量的增加而增加,因为您不必执行检查每个请求。这意味着您在实际失去可用性和检测到可用性损失之间有几秒钟的窗口,但在此期间通过的请求无论如何都会失败。

HAProxy——可能还有其他工具,比如 Varnish 或 Nginx——也可以帮助您以其他方式处理正常的故障,方法是在 API 端点之前的一层超时失败的请求,以便调用者得到响应,即使服务本身没有响应。我的一个环境中的一个示例是购物页面,当站点访问者按类别浏览项目时,应用程序会调用外部 API。如果这个请求运行的时间比它应该运行的时间长,代理可以中断请求并向系统返回一个预先配置的静态错误页面,并返回一个带有错误的系统——比如说,在 JSON 或 XML 中,请求应用程序可以理解——这样硬故障变成了软故障。例如,在这种情况下,这个虚假响应可以返回一个空的 JSON 数组,其中包含“找到的项目”。

现在,我并不完全清楚这些 API 是您的,还是您正在聚合的外部 API。如果是后者,那么 HAProxy 在这里也是一个很好的解决方案,但面向另一个方向 - 后端朝外,您的服务与它的前端联系。您通过代理访问外部服务,代理检查远程服务,如果目标 API 不健康,将立即向您的应用程序返回错误。我使用此解决方案从我的一个应用程序访问外部故障单系统。这里的另一个优势是,代理日志允许我收集有关传递给该外部服务的所有许多请求的使用、性能和可靠性数据,而不管数十个内部系统中的哪个可以访问它,其可见性远高于如果我尝试从访问该外部服务的所有内部应用程序服务器收集它,我可以做到这一点。

【讨论】:

  • 迈克尔,这是非常详细的,正是我感兴趣的答案。让我澄清一下,我假设管理员“关闭”服务器将需要至少 5 分钟的等待时间在实际做任何事情以确保没有用户处于交易中间之前。如果用户处于多个 API 调用的中间,则系统已经正常——只有在 API 调用中才会出现问题。而我们正在轮询的状态表与所有其他事务数据都位于同一台 mysql 服务器上,因此如果一个状态表出局,则整个系统都已关闭。另外:我的 API。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多