API の信頼性を向上させる 5 つの方法

API はデジタル世界で重要な役割を果たし、さまざまなアプリケーションの相互通信を可能にします。ただし、これらの API の信頼性は、API に依存するアプリケーションが適切に機能し、一貫して動作することを保証する上で重要な要素です。この記事では、API の信頼性を向上させるための 5 つの主な戦略について説明します。

1. 徹底したテスト

API の信頼性を確保するための最初のステップは、徹底的なテストです。実行する必要があるテストには、API が正しく動作していることを確認する機能テスト、API が他のシステムと適切に動作することを確認する統合テスト、大規模な使用時に API がどのように動作するかを理解するための負荷テストが含まれます。

自動テストは開発サイクルの早い段階で問題を発見でき、回帰テストは新しい変更によって既存の機能が損なわれないことを確認できます。仮想化またはモック技術を使用して、API の依存関係をシミュレートしてより詳細なテストを行うことができます。さらに、API のプロバイダーとコンシューマーの両方が合意されたインターフェイスを満たしていることを確認するには、コントラクト テストが非常に重要です。

以下では、Go の組み込みテスト パッケージを使用して、簡単な例を通じて仮想の 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 のバージョン管理にさまざまな方法を使用できます。

次の例は、API バージョンを URL に埋め込むことでバージョン管理を実装する方法を示しています。このアプローチは、「パス バージョン管理」とよく呼ばれます。

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 の 2 番目のバージョンに対応します。ブランチを追加することで、より多くのバージョンとエンドポイントに対応できるようにこのパターンを簡単に拡張できます。

あるいは、カスタム ヘッダーまたはメディア タイプのバージョン管理 (「コンテンツ ネゴシエーション」とも呼ばれます) を通じてバージョン管理を実装することもできます。

選択したバージョン管理戦略に関係なく、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 は 、さまざまな言語でのサービスの測定をサポートするクライアント ライブラリが組み込まれたオープン ソース システムの監視およびアラート ツールキットです。ここでは、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 の 2 つのメトリクスを作成して登録します。前者はリクエストが受信されるたびに増加するカウンターであり、後者は各リクエストの処理に費やされた時間を記録する集計されたメトリックです。

次に、リクエストが処理されるたびにカウンターをインクリメントし、リクエストの実行時間を測定する HTTP ハンドラーを作成しました。これらのメトリクスは、promhttp.Handler() を使用して /metrics エンドポイントで公開します。

これで、サーバーを起動してサーバーにリクエストを送信するとすぐに、http://localhost:8080/metrics にアクセスするか、curl などのツールを使用してこれらのメトリクスを表示できるようになります。

これは単なる基本的な例であり、実際には、より多くのメトリクスを追跡し、他のディメンション (HTTP メソッド、応答ステータス コードなど) に基づいてそれらをセグメント化することができます。

5. APIゲートウェイを活用する

API ゲートウェイは、API の堅牢性を効果的に向上させる強力なツールです。API ゲートウェイはシステムの統合入口として、ルーティング、負荷分散、認証、電流制限などの複数の機能を処理できます。API 本体からこれらの懸念事項を抽象化することで、インフラストラクチャではなくビジネス ロジックに重点を置くことができます。

さらに、API Gateway は、自動フェイルオーバー、パフォーマンス向上のための応答のキャッシュ、高負荷時のリクエストのバッファリングやキューイングなどの追加の復元機能を提供できます。

以下に、テクノロジー スタックに適切な API ゲートウェイを選択するのに役立つ API ゲートウェイが提供できる機能の一部を示します。

  1. リクエストのルーティング:  API ゲートウェイは、リクエスト内のルーティング情報に基づいて、クライアント リクエストを適切なバックエンド サービスにルーティングできます。
  2. API バージョン管理:  API ゲートウェイは API の複数のバージョンを管理できるため、クライアントは異なるバージョンを並行して使用できます。
  3. 電流制限: バックエンド サービスに過剰なリクエストが殺到するのを避けるために、API ゲートウェイはクライアントまたはクライアント グループのリクエスト レートを制限できます。
  4. 認証と認可:  API ゲートウェイは通常、クライアント リクエストの認証と認可を処理し、認証および認可されたリクエストのみがバックエンド サービスに到達するようにします。
  5. API キー管理:  API ゲートウェイは通常、API の使用方法を追跡および制御するために使用される API キーを管理します。
  6. キャッシュ: パフォーマンスを向上させ、バックエンド サービスの負荷を軽減するために、API Gateway はバックエンド サービスからの応答をキャッシュし、同じリクエストを受信したときにキャッシュされた応答を返すことができます。
  7. リクエストとレスポンスの変換:  API ゲートウェイは、リクエストとレスポンスをクライアントまたはバックエンド サービスが必要とする形式に変換できます。
  8. サーキット ブレーカー機能: サービスに障害が発生した場合、API ゲートウェイはリクエストを機能しているサービスにルーティングすることで、アプリケーションのクラッシュを防ぐことができます。
  9. 監視と分析:  API Gateway は、分析、監視、アラートのために API の使用状況とパフォーマンス データを収集できます。
  10. セキュリティ ポリシー:  API Gateway は、SQL インジェクションやクロスサイト スクリプティング (XSS) などのセキュリティ脅威を防止しながら、IP ホワイトリストなどのセキュリティ ポリシーを実装できます。

有名なオープンソース API ゲートウェイをいくつか示します。

  1. Kong : Kong は、クラウドネイティブで高速かつスケーラブルな分散型マイクロサービス管理レイヤー (API ゲートウェイまたは API ミドルウェアとも呼ばれます) です。2015 年からオープン ソース プロジェクトとして存在し、そのコア機能は Lua で記述され、Nginx Web サーバー上で実行されます。
  2. Tyk : Tyk は、高速に実行され、拡張性が高いオープン ソースの API ゲートウェイであり、スタンドアロン サーバー上で実行することも、既存の Nginx インストールと連動させることもできます。
  3. Express Gateway : Express Gateway は、Express.js 上に構築されたマイクロサービス API ゲートウェイです。ゲートウェイは完全にスケーラブルであり、特定のフレームワークに依存せず、堅牢でスケーラブルなソリューションを短期間で提供できます。
  4. KrakenD : KrakenD は、高性能のオープンソース API ゲートウェイです。KrakenD は、SOA アーキテクチャの複雑さをすべて取り除き、アプリケーション開発者が優れたパフォーマンスを維持しながら新しい機能を迅速にリリースできるようにします。

全体として、API の信頼性の向上は 1 回限りの作業ではなく、継続的な取り組みです。これには、厳格なテスト、正確なバージョン管理、優れた設計原則の遵守、API ゲートウェイなどのツールのインテリジェントな使用、継続的な監視と分析が含まれます。これらの戦略を導入すると、時の試練に耐え、アプリケーションに強固な基盤を提供する API を構築できるようになります。

元のタイトル: https://www.codereliant.io/5-ways-to-improve-your-api-reliability/


優れたツールをもっと見る

宇宙エレベーター、MOSS、ChatGPTなどはすべて、2023年が平凡な年になる運命にないことを示しています。新しいテクノロジーはすべて精査する価値があり、私たちはこの感性を持つべきです。

ここ数年、漠然とローコードに出会ったのですが、現在では比較的人気があり、大手メーカーも続々と参入しています。

ローコード プラットフォームのコンセプト: 自動コード生成とビジュアル プログラミングにより、少量のコードだけでさまざまなアプリケーションを迅速に構築できます。

私の考えでは、ローコードとは、フロントエンド、バックエンド、データベースをすべて一度に実行できるシステムを、ドラッグしたり、動かしたり、ワンパス操作で作成したりすることです。もちろんこれが最終目標かもしれません。

リンク: www.jnpfsoft.com/?csdn、興味があれば、こちらも試してみてください。

JNPF の利点は、フロントエンド コードとバックエンド コードを生成できることです。これにより、優れた柔軟性が得られ、より複雑でカスタマイズされたアプリケーションを作成できます。また、そのアーキテクチャ設計により、開発者は基礎となる技術的な詳細を気にすることなく、アプリケーション ロジックとユーザー エクスペリエンスの開発に集中できます。

おすすめ

転載: blog.csdn.net/Z__7Gk/article/details/131856993