计算 API 服务中的 API 调用的有效方法
Effective way to count the API calls in an API service
我是在 DRF 的背景下问这个问题的,但这也可以推广。我们正在维护一项 API 服务,我们正在为 1K+ 实时请求提供服务。在当前情况下,我们正在实时计算 API 次调用,即我们正在更新数据库列 API 次调用针对每个 API 次调用的用户计数。
但是有什么有效的方法吗?例如,在其他地方记录 API 调用,然后在几分钟后更新数据库?还是我们现在正在做的很好?多大规模的 API 服务可能会处理这个问题?网络上没有针对此问题的具体内容。
Redis 是内存中的键值数据存储,因此可以非常快速地检索数据。使用 Redis 实现 速率限制并验证 API 调用的数量 也非常简单。即
- 像用户的 IP 地址一样存储密钥
- 增加从该 IP 发出的调用次数
Redis Link
Redis 实验室 Link
如果您的应用程序正在将其日志写入 stdout
,您可以轻松地将其连接到日志数据库,例如 Elasticsearch,然后计算请求数。您还可以创建非常详细的仪表板,显示您的用户正在使用您的 API.
如果您使用像 NGINX 这样的 Web 服务器来为您的 API 提供服务,您甚至不需要读取应用程序服务器的输出。您可以将其 stdout
日志通过管道传输到数据库中。无论来源如何,让外部进程直接从 stdout
读取都比您在应用程序层上执行的任何写入操作的性能更高。
将您的日志视为事件流是“十二因素应用程序”方法论中描述的 12 个因素之一。您可以在其网站上找到有关此方法的更多信息:
我不建议您在应用程序级别实现此功能,而是使用网络中间件来执行此操作。
正如@guzmonne 所说,您可以直接读取 Nginx 日志,也可以借助一些工具,例如 Filebeat/Logstash。
在我的公司,我们使用 Filebeat 从容器(多个 Kubernetes 集群中的 300 多个节点)和其他独立服务收集日志(不仅是 API 调用),所有这些都转到 Elasticsearch 分析日志的集群。
我们不计算 API 次调用,但我们确实关心失败率,当有太多非 200 HTTP 请求时,有一些 Prometheus 规则发送警报。
您似乎在使用 Django,所以我的建议是在此处利用 Memcached:https://docs.djangoproject.com/en/3.2/topics/cache/
Memcached 是一种内存存储,与 Django 配合得很好,并且比 Redis 更简单(但功能也更少)。 Memcached 确保您的计数器在所有 Python 进程中同步,这对于 Django 服务器至关重要。
您可以使用 cache.incr()
增加跟踪 API 调用的计数器,并针对每个用户请求使用 cache.get()
检查计数器。
由于 Memcached 是“内存中的”,数据不会永远保留,因此您还可以在数据库中增加一个计数器 异步(您不想阻塞您的用户要求)。为了使数据库计数器递增更有效,您应该使用 F()
表达式 (https://docs.djangoproject.com/en/3.2/ref/models/expressions/#f-expressions).
除了有用的答案,我发现更好的解决方案是使用 API 网关。我们选择了 Kong。如果您要在 API 服务上收到大量请求,那么将授权、日志记录和其他任务移交给 API 网关是更好的方法。除了自托管 API 网关解决方案,您还可以找到来自 Google、AWS 和其他提供商的托管服务。它是这样工作的:
- 您的 API 服务应该只做它们应该做的事情
- 将 Kong 或任何其他 API 网关放在您的 API 服务前面
- 使用 API 网关处理授权、日志记录等
- 将请求日志从网关发送到仪表板等外部服务,或者用它们做任何您想做的事情
我们选择了这种设计,现在我们可以很容易地扩展。这种设计使我们能够保持服务清洁,并帮助我们避免单体架构。我仍然不确定更大的参与者是如何构建他们的 APIs 以及他们如何处理授权、日志记录等,但经过大量试验和错误后我发现工作得很好的是分发跨软件的责任,这些责任被设计为以最好的方式完成一项任务。
除了授权和限速功能,Kong(可能还有其他 API 网关)也可以进行负载均衡。这将使您可以扩展 API 服务,而不必担心破坏事物。
我是在 DRF 的背景下问这个问题的,但这也可以推广。我们正在维护一项 API 服务,我们正在为 1K+ 实时请求提供服务。在当前情况下,我们正在实时计算 API 次调用,即我们正在更新数据库列 API 次调用针对每个 API 次调用的用户计数。
但是有什么有效的方法吗?例如,在其他地方记录 API 调用,然后在几分钟后更新数据库?还是我们现在正在做的很好?多大规模的 API 服务可能会处理这个问题?网络上没有针对此问题的具体内容。
Redis 是内存中的键值数据存储,因此可以非常快速地检索数据。使用 Redis 实现 速率限制并验证 API 调用的数量 也非常简单。即
- 像用户的 IP 地址一样存储密钥
- 增加从该 IP 发出的调用次数
Redis Link
Redis 实验室 Link
如果您的应用程序正在将其日志写入 stdout
,您可以轻松地将其连接到日志数据库,例如 Elasticsearch,然后计算请求数。您还可以创建非常详细的仪表板,显示您的用户正在使用您的 API.
如果您使用像 NGINX 这样的 Web 服务器来为您的 API 提供服务,您甚至不需要读取应用程序服务器的输出。您可以将其 stdout
日志通过管道传输到数据库中。无论来源如何,让外部进程直接从 stdout
读取都比您在应用程序层上执行的任何写入操作的性能更高。
将您的日志视为事件流是“十二因素应用程序”方法论中描述的 12 个因素之一。您可以在其网站上找到有关此方法的更多信息:
我不建议您在应用程序级别实现此功能,而是使用网络中间件来执行此操作。
正如@guzmonne 所说,您可以直接读取 Nginx 日志,也可以借助一些工具,例如 Filebeat/Logstash。
在我的公司,我们使用 Filebeat 从容器(多个 Kubernetes 集群中的 300 多个节点)和其他独立服务收集日志(不仅是 API 调用),所有这些都转到 Elasticsearch 分析日志的集群。
我们不计算 API 次调用,但我们确实关心失败率,当有太多非 200 HTTP 请求时,有一些 Prometheus 规则发送警报。
您似乎在使用 Django,所以我的建议是在此处利用 Memcached:https://docs.djangoproject.com/en/3.2/topics/cache/
Memcached 是一种内存存储,与 Django 配合得很好,并且比 Redis 更简单(但功能也更少)。 Memcached 确保您的计数器在所有 Python 进程中同步,这对于 Django 服务器至关重要。
您可以使用 cache.incr()
增加跟踪 API 调用的计数器,并针对每个用户请求使用 cache.get()
检查计数器。
由于 Memcached 是“内存中的”,数据不会永远保留,因此您还可以在数据库中增加一个计数器 异步(您不想阻塞您的用户要求)。为了使数据库计数器递增更有效,您应该使用 F()
表达式 (https://docs.djangoproject.com/en/3.2/ref/models/expressions/#f-expressions).
除了有用的答案,我发现更好的解决方案是使用 API 网关。我们选择了 Kong。如果您要在 API 服务上收到大量请求,那么将授权、日志记录和其他任务移交给 API 网关是更好的方法。除了自托管 API 网关解决方案,您还可以找到来自 Google、AWS 和其他提供商的托管服务。它是这样工作的:
- 您的 API 服务应该只做它们应该做的事情
- 将 Kong 或任何其他 API 网关放在您的 API 服务前面
- 使用 API 网关处理授权、日志记录等
- 将请求日志从网关发送到仪表板等外部服务,或者用它们做任何您想做的事情
我们选择了这种设计,现在我们可以很容易地扩展。这种设计使我们能够保持服务清洁,并帮助我们避免单体架构。我仍然不确定更大的参与者是如何构建他们的 APIs 以及他们如何处理授权、日志记录等,但经过大量试验和错误后我发现工作得很好的是分发跨软件的责任,这些责任被设计为以最好的方式完成一项任务。
除了授权和限速功能,Kong(可能还有其他 API 网关)也可以进行负载均衡。这将使您可以扩展 API 服务,而不必担心破坏事物。