您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

提升 API 可靠性的五种方法

时间:2023-07-21 16:00:06  来源:51CTO  作者:

译者 | 刘汪洋

API 在我们的数字世界中发挥着关键的作用,使各种不同的应用能够相互通信。然而,这些 API 的可靠性是保证依赖它们的应用程序功能正常、性能稳定的关键因素。本文,我们将探讨提高 API 可靠性的五种主要策略。

 

1.全面测试

要确保 API 的可靠性,第一步是进行全面的测试。需要进行的测试包括:功能测试以验证 API 的正确运行,集成测试以确保 API 能与其他系统正常协同,以及负载测试以理解 API 在大规模使用下的表现。

自动化测试能在开发周期的早期发现问题,回归测试能保证新的修改不会对现有功能造成破坏。使用虚拟化或模拟技术可以模拟 API 依赖,进行更深度的测试。此外,为了确保 API 的提供者和消费者都能满足约定的接口,契约测试非常重要。

下面我们将使用 Go 的内置 testing 包,通过一个简单的例子对一个假设的 API 端点(用于访问 API 的 URI)进行测试。

假设我们有一个端点 GET /users/{id} ,用于返回用户的详细信息。

下面是我们可能编写的测试代码:

复制

package mAIn

import (

".NET/http"

"net/http/httptest"

"testing"

// 这是一个简化的实际处理器函数示例

func UserHandler(w http.ResponseWriter, r *http.Request) {

// ... 处理器逻辑

}

func TestUserHandler(t *testing.T) {

req, err := http.NewRequest("GET", "/users/1", nil)

if err != nil {

t.Fatal(err)

}

rr := httptest.NewRecorder()

handler := http.HandlerFunc(UserHandler)

handler.ServeHTTP(rr, req)

if status := rr.Code; status != http.StatusOK {

t.Errorf("handler returned wrong status code: got %v want %v",

status, http.StatusOK)

}

// 你还可以检查响应体是否符合预期的输出

expected := `{"id": "1", "name": "John Doe"}`

if rr.Body.String() != expected {

t.Errorf("handler returned unexpected body: got %v want %v",

rr.Body.String(), expected)

}

}

这个测试创建了一个新的 HTTP 请求,模拟了对我们的 /users/{id} 端点的调用,然后把请求传递给了处理器函数。测试会检查响应状态是否为 200 OK(即我们期望的成功请求应返回的结果)以及响应体是否与预期的输出一致。

这个例子只是一个简单的示例,在实际应用中,你可能会面临更复杂的场景,包括测试各种边界条件、错误路径等。此外,net/http/httptest 包提供了许多用于测试 HTTP 客户端和服务器的工具。

总之,你可以结合单元测试、性能测试和持续的集成测试,为你的 API 构建一个全面的测试套件。

单元测试的目的是确保你的 API 中每个组件的正确性。它通过验证每个部分的功能和隔离它们,使得你可以在早期发现并纠正问题。单元测试通常通过模拟依赖项并独立测试函数来完成。在 Go 语言中,可以利用诸如 testify 等包来达成这一目标。

性能测试则是为了在高流量的情况下对 API 进行压力测试。这种测试有助于你确定系统在高负载情况下的表现,识别瓶颈,并确保 API 能处理真实世界的使用情况。性能测试可以使用 JMeter 或Gatling 等工具进行。

最后,持续集成测试则通过模拟用户或客户端对 API 进行一系列连续操作,来测试系统的工作流程。这类测试能够提供对端到端工作流程、潜在的障碍或延迟,以及整体用户体验的深入理解。这个过程可以自动化并集成到你的 CI/CD 流程中,使得你可以持续监控并及时反馈任何代码更改的影响。

通过实施包括功能测试、单元测试、性能测试和持续合成测试在内的全面的测试策略,你可以确保你的 API 不仅稳定且高性能,还能为使用者提供无缝的体验。而在问题出现时,这种多元化的测试方法可以帮助你快速定位并解决问题的根源。

2.版本控制

在维护软件系统的稳定性方面,API 版本管理扮演了核心角色。随着时间推移,API 可能会随着需求变化和优化,如果没有适当的版本管理,可能会对现有的客户端应用造成破坏。这就是 API 版本管理的关键所在。通过维护 API 的各个版本,你可以在引入新功能和优化的同时,确保不影响使用旧版本 API 的应用。

这种策略提升了系统的稳定性,因为即使 API 经过改动和优化,客户端应用依然可以稳定运行。它让开发者能够部署 API 更新,而不需要担心这些变化会对正在运行的应用造成破坏,保障了系统的稳定性和正常运行。

保持向后兼容性是实现 API 稳定性的关键一环,也就是说,新系统应能与旧版 API 兼容。即使新的版本发布,使用旧 API 版本的应用依然可以正常运行。这避免破坏用户体验,并给了开发者足够的时间,让他们可以按照自己的节奏更新应用以适应新的 API ,而不是为了防止应用出错而被迫升级。这样做,有助于创建一个整体上更稳定、更强大和更具有弹性的系统。

示例

在 Go 语言中,我们可以使用多种方式来进行 API 的版本管理。

下面这个例子展示了如何通过在 URL 中嵌入 API 版本实现版本管理,这种方法通常被称为"路径版本控制"。

复制

package main

import (

"fmt"

"net/http"

func handleRequest(w http.ResponseWriter, r *http.Request) {

switch r.URL.Path {

case "/v1/users":

fmt.Fprintf(w, "You've hit the version 1 of the users API!")

case "/v2/users":

fmt.Fprintf(w, "You've hit the version 2 of the users API!")

default:

http.NotFound(w, r)

}

}

func main() {

http.HandleFunc("/", handleRequest)

http.ListenAndServe(":8080", nil)

}

在这个例子中,我们定义了一个处理函数,它根据请求的 URL 路径来匹配响应的代码。当访问 "/v1/users" 路径时,我们认为这是对我们 API 第一版本的请求。同样地,"/v2/users" 则对应我们 API 的第二个版本。通过添加更多的分支,你可以轻松地扩展这种模式以适应更多版本和端点。

此外,你也可以通过自定义头部或媒体类型版本管理(也称为"内容协商")来实现版本管理。

不论你选择何种版本管理策略,都应为 API 的每个版本维护清晰且最新的文档,这是一种良好的实践。

但是,我们也需要谨慎使用版本管理。我们应尽可能地保持向后兼容性,并提供清晰的文档。文档应详细说明每个新版本中的变化,并提供废弃旧版本的合理时间表。

3. 面向失败设计

在理想情况下,API 始终能够正确运行。然而在实际操作中,出现失败的情况并不罕见。在设计 API 的过程中,我们需要考虑其容错能力,这可能涉及到诸如优雅降级(即系统继续运行但是功能有所缩减)和故障转移机制(即出现故障时,系统自动切换到备份系统)等策略。

将明确的错误消息和代码纳入 API,能有助于应用程序更好地理解问题所在以及采取应对策略。我们可以通过重试逻辑、速率限制和断路器,让系统从临时性问题中恢复,避免故障级联。

下图显示了应对各种故障类型的操作方法:

示例:断路器模式

在断路器模式中,Go 语言有一个叫 go-hystrix 的热门库,该库专注于延迟和容错处理。它主要是在服务停止时,通过快速失败阻止故障级联。以下是一个基本示例:

复制

package main

import (

"Github.com/afex/hystrix-go/hystrix"

"log"

"net/http"

"errors"

func main() {

hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{

Timeout: 1000,

MaxConcurrentRequests: 100,

ErrorPercentThreshold: 25,

})

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

err := hystrix.Do("my_command", func() error {

// 调用其他服务

return nil

}, nil)

if err != nil {

log.Printf("Failed to talk to other services: %v", err)

http.Error(w, "Failed to talk to other services", http.StatusInternalServerError)

}

})

log.Fatal(http.ListenAndServe(":1234", nil))

}

在上述示例中,我们将一个命令封装在 hystrix.Do() 中。如果基于我们设置的参数,传入 Do() 的函数失败或超时,断路器就会被触发,后续的调用将会立即失败,而不再调用该函数。

请注意,这只是一个基本的示例,实际应用场景将涉及更多复杂的用法,需要针对这个库以及其他的弹性实用程序库涉及的各种参数进行细致调整。请务必阅读各种库的文档,深入理解如何在你的代码中有效地使用它们。

4. 监控与分析

实时监控与及时分析对于保证 API 的稳定性至关重要。执行一套全面的 API 监控策略可以包括对运行时间、性能以及错误的检测,这有助于我们在问题扩散影响用户前,及时发现并处理。

同时,深入分析 API 的使用模式可以让我们得到重要的洞察。了解到高峰负载时段、最常使用的端点以及其他使用详情后,您就可以主动地找出可能存在的弱点,并据此进行 API 优化。

选择正确的指标去追踪,对于了解你的 API 的健康状态和性能至关重要。以下是一些需要考虑的关键指标:

1.吞吐量:您的 API 单位时间内处理的请求数量,可以进一步分为端点、HTTP 方法(如 GET、POST、PUT、DELETE 等)或响应状态码。

2.错误率:单位时间内的错误响应数量,通常是指含有 4xx 或 5xx 状态码的响应。同吞吐量一样,这个指标也可以按端点、HTTP 方法或具体的状态码进行细分。

3.延迟:处理一个请求所需的时间,通常以一系列百分位数(如第 50、95 和 99 百分位)来追踪,这可以帮助您了解典型和极端情况下的性能表现。您可能需要针对不同的端点或 HTTP 方法单独追踪此项。

4.流量:发送和接收的数据量,可以按端点、HTTP 方法或响应状态码进行细分。

5.可用性:您的 API 正常运行并能够处理请求的时间占比,可以作为一个整体进行测量,或者针对每一个单独的端点进行测量。

6.饱和度:系统达到最大容量的程度,这可以通过测量 CPU 使用率、内存使用率、磁盘 I/O 或其他可能限制系统处理更多负载的资源来了解。

7.断路器触发:如果您使用断路器模式处理故障,您可能需要追踪断路器被触发的频率,这可以帮助您了解 API 或其依赖项失败的频率。

请记住,根据你的 API 特性和应用需求,选择追踪的具体指标可能会有所不同。关键是要选择那些能为你提供有意义的 API 健康状况和性能洞察力的指标。

以 Prometheus 为例:

Prometheus 是一款内建客户端库的开源系统监控和警告工具包,它支持用各种语言度量您的服务。下面就是一个示例,说明如何使用 Go 客户端库在 HTTP 端点上展示指标。

我们将使用 Prometheus 的 Go 客户端 来展示和创建这些指标。

复制

package main

import (

"net/http"

"github.com/prometheus/client_golang/prometheus"

"github.com/prometheus/client_golang/prometheus/promhttp"

var (

httpRequestsTotal = prometheus.NewCounterVec(

prometheus.CounterOpts{

Name: "http_requests_total",

Help: "Number of HTTP requests",

},

[]string{"path"},

httpRequestDuration = prometheus.NewSummaryVec(

prometheus.SummaryOpts{

Name: "http_request_duration_seconds",

Help: "Duration of HTTP requests in seconds",

},

[]string{"path"},

func init() {

// Register the metrics.

prometheus.MustRegister(httpRequestsTotal)

prometheus.MustRegister(httpRequestDuration)

}

func handler(w http.ResponseWriter, r *http.Request) {

// Increment the counter for the received requests.

httpRequestsTotal.WithLabelValues(r.URL.Path).Inc()

// Measure the time it took to serve the request.

timer := prometheus.NewTimer(httpRequestDuration.WithLabelValues(r.URL.Path))

defer timer.ObserveDuration()

// Handle the request.

w.Write([]byte("Hello, world!"))

}

func main() {

http.HandleFunc("/", handler)

// Expose the registered metrics via HTTP.

http.Handle("/metrics", promhttp.Handler())

http.ListenAndServe(":8080", nil)

}

在这个例子中,我们创建并注册了两个指标:http_requests_total 和 http_request_duration_seconds。前者是一个计数器,每接收到一个请求就增加一次计数,后者是一个汇总指标,用于记录处理每个请求所花费的时间。

然后,我们创建了一个 HTTP 处理器,每处理一个请求,就会增加计数器并测量请求的执行时长。我们利用 promhttp.Handler() 在 /metrics 端点上展示这些指标。

现在,只要你启动了服务器并向其发送请求,就可以通过访问 http://localhost:8080/metrics 或者使用工具如 curl 来查看这些指标。

这只是一个基础的示例,在实际应用中,你可能会希望追踪更多的指标,并基于其他维度(如 HTTP 方法、响应状态码等)对它们进行细分。

5. 利用 API 网关

API 网关是一种强大的工具,能有效提升 API 的健壮性。作为系统的统一入口,API 网关能够处理诸如路由、负载均衡、认证、限流等多项功能。通过将这些问题从 API 本体中抽离,你能更专注于业务逻辑,而非基础设施。

另外,API 网关还可提供额外的弹性特性,如自动故障转移、为提高性能而对响应进行缓存,以及在高负载时对请求进行缓冲或排队。

下面列出了 API 网关能提供的部分功能,帮助你为技术栈选择适合的 API 网关:

  1. 请求路由: API 网关可以依据请求中的路由信息将客户端请求路由到合适的后端服务。
  2. API 版本管理: API 网关能管理多版本的 API,允许客户端并行使用不同版本。
  3. 限流: 为了避免请求过量淹没后端服务,API 网关能够限制某个或某组客户端的请求速率。
  4. 身份验证和授权: API 网关通常处理客户端请求的身份验证和授权,确保只有经过验证并授权的请求才能到达后端服务。
  5. API 密钥管理: API 网关通常管理 API 密钥,这些密钥用于跟踪和控制 API 的使用方式。
  6. 缓存: 为了提升性能并降低后端服务的负载,API 网关可以缓存后端服务的响应,并在收到相同的请求时返回缓存的响应。
  7. 请求和响应转换: API 网关可以将请求和响应转换为客户端或后端服务所需的格式。
  8. 熔断器功能: 当服务出现故障,API 网关可以通过将请求路由到正常运行的服务来防止应用程序崩溃。
  9. 监控和分析: API 网关能收集 API 的使用和性能数据,用于分析、监控和警报。
  10. 安全策略: API 网关可以执行安全策略,如 IP 白名单,同时防止 SQL 注入、跨站脚本攻击(XSS)等安全威胁。

以下是一些知名的开源 API 网关:

  1. Kong:Kong 是一个云原生、快速、可扩展、分布式的微服务管理层(也称为 API 网关或 API 中间件)。自 2015 年以来,它以开源项目的形式存在,其核心功能是用 Lua 编写的,并运行在 Nginx 网络服务器上。
  2. Tyk:Tyk 是一个开源的 API 网关,运行速度快且可扩展性强,既可以运行在独立服务器上,也可与已有的 Nginx 安装进行协同工作。
  3. Express Gateway:Express Gateway 是一个基于 Express.js 构建的微服务 API 网关。该网关完全可扩展,不依赖任何特定框架,能够在短时间内提供强大且可扩展的解决方案。
  4. KrakenD:KrakenD 是一个高性能的开源 API 网关。KrakenD 消除了所有 SOA 架构的复杂性,以支持应用程序开发者快速发布新功能,同时保持出色的性能。

总的来说,提升 API 的可靠性不是一项一次性任务,而是需要持续投入的工作。这包括严格的测试、精确的版本控制、遵循好的设计原则,智能地使用如 API 网关这样的工具,以及持续的监控和分析。有了这些策略,你就能构建出能经受住时间考验并为你的应用程序提供可靠基础的 API。

译者介绍

刘汪洋,51CTO社区编辑,昵称:明明如月,一个拥有 5 年开发经验的某大厂高级 JAVA 工程师,拥有多个主流技术博客平台博客专家称号。

原文标题:5 Ways to Improve Your API Reliability,作者:CodeReliant 社区



Tags:API   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
中国三大运营商共同发布通过GSMA Open Gateway认证的一次性密码 API
3月26日,北京:中国三大领先的移动运营商——中国移动、中国电信和中国联通今日发布商用OTP API(一次性密码API)服务,并通过了GSMA Open Gateway认证。此次发布标志着中...【详细内容】
2024-03-26  Search: API  点击:(18)  评论:(0)  加入收藏
如何免费访问和使用Gemini API?
Gemini是谷歌开发的一个新模型。有了Gemini可以为查询提供图像、音频和文本,获得几乎完美的答案。 我们在本教程中将学习Gemini API以及如何在机器上设置它。我们还将探究各...【详细内容】
2024-02-19  Search: API  点击:(59)  评论:(0)  加入收藏
构建 Web API 的两种流行选择:REST vs GraphQL
在 RESTful 和 GraphQL API 之间的选择取决于您的具体用例。RESTful API 适用于需要高可伸缩性的简单应用程序,而 GraphQL 则适用于具有不同数据需求的复杂应用程序。简介RES...【详细内容】
2024-01-09  Search: API  点击:(63)  评论:(0)  加入收藏
FastAPI:高性能Web框架的简介与应用
正文:在当今互联网时代,构建高性能的WebAPI是许多开发人员的关注重点。而FastAPI作为一个现代、快速的Web框架,为基于标准Python类型提示的API构建提供了强大的支持。FastAPI的...【详细内容】
2023-12-27  Search: API  点击:(101)  评论:(0)  加入收藏
理解 Spark 写入 API 的数据处理能力
这张图解释了 Apache Spark DataFrame 写入 API 的流程。它始于对写入数据的 API 调用,支持的格式包括 CSV、JSON 或 Parquet。流程根据选择的保存模式(追加、覆盖、忽略或报...【详细内容】
2023-12-13  Search: API  点击:(149)  评论:(0)  加入收藏
如何在Python中使用ChatGPT API处理实时数据
译者 | 李睿审校 | 重楼OpenAI公司推出的GPT如今已经成为全球最重要的人工智能工具,并精通基于其训练数据处理查询。但是,它不能回答未知话题的问题,例如: 2021年9月之后的近期...【详细内容】
2023-12-13  Search: API  点击:(227)  评论:(0)  加入收藏
伪原创API是什么?六个角度了解伪原创API
伪原创API,听起来可能对许多人来说是一个陌生的术语。然而,在当今数字化时代,尤其是在内容创作和网络营销领域,伪原创API正逐渐崭露头角。在本文中,我将向您深入介绍伪原创API是...【详细内容】
2023-12-11  Search: API  点击:(156)  评论:(0)  加入收藏
使用FastAPI部署YOLO模型的步骤
在计算机视觉领域,You Only Look Once (YOLO) 算法已经崭露头角,成为一种改变游戏规则的算法。它承诺具有卓越准确性的实时目标检测,使其成为从监视和自动驾驶车辆到图像和视频...【详细内容】
2023-12-06  Search: API  点击:(157)  评论:(0)  加入收藏
构建强大REST API的十个最佳实践
在项目开发中,我们经常会使用REST风格进行API的定义,这篇文章为大家提供10条在使用REST API时的最佳实践。希望能够为你带来灵感和帮助。1、使用具体且有意义的资源名称选择能...【详细内容】
2023-12-06  Search: API  点击:(149)  评论:(0)  加入收藏
前端请求到后端API的中间件流程解析
在前端请求到后端API的典型流程中,经过一系列中间件的处理,确保请求的顺利处理和安全性。以下是中间件的详细解析:1. 前端请求用户在前端发起请求,包括请求的URL、参数、以及其...【详细内容】
2023-12-06  Search: API  点击:(122)  评论:(0)  加入收藏
▌简易百科推荐
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(5)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(12)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(8)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(10)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(8)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  云原生散修  微信公众号  Tags:Kubernetes   点击:(6)  评论:(0)  加入收藏
站内最新
站内热门
站内头条