花園里充滿了美麗的事物,但也有很多可能出錯的地方

錯誤1:查詢不變的信息

當我構建 Avalara AvaTax REST API 時,我必須允許用戶發送地址。由于他們的數據很亂,有時他們會發送 ISO 國家代碼,或者可能是國家名稱,也可能是別名。我可以處理這個問題,因為 GitHub 上有很多具有寬松許可證的 國家數據源 ,但最終我選擇付費購買 官方 ISO 3166 國家代碼列表 。

下一步是讓我的 API 服務器在啟動時加載這些數據。代碼不必太復雜——這里有一些類似 C# 的偽代碼,大致顯示了如何使其工作:

private  static Task<List<Country>>? _cachedQuery = null ; 

private Task<List<Country>> GetCachedCountries()
{
// 將承諾保存到靜態變量
if (_cache == null ) {
_cache = Database.Countries.ToListAsync();
}

// 所有調用者加入同一個承諾
return _cache;
}

為什么要這樣做?幸運的是,新國家/地區并不經常創建。如果國家/地區列表要更改,我們會在每月的應用程序部署期間發送 SQL 腳本來添加新記錄。

我的 C# API 服務器不是查詢數據庫中的表,而是將這些數據保存在單例中。它會在輸入或輸出時查找正確的名稱。數據只占用幾千字節,為了方便起見,我有多個散列的不區分大小寫的字典。

您可能有幾十個這樣的靜態數據集。查找數據集、原因代碼、配置標志 — 將它們存儲在靜態單例中!如果您忘記了,您可能會發現您的系統每秒對永遠不會改變的數據進行數千次不必要的查詢。

錯誤2:過度使用數據庫的狀態頁面檢查

您的 API 服務器需要一個健康檢查系統。它可以是一個頁面或一個 API,但它應該執行一系列基本功能測試,以確保機器能夠正常工作。典型的測試包括:

這些類型的狀態檢查對于啟動作為自動擴展組一部分的服務器或使用容器化啟動模板是必不可少的。在部署服務器之前,徹底測試所有內容非常重要——啟動缺少數據庫連接字符串的機器會很糟糕。

這些狀態檢查的一個副作用是,它們通常也用于監控部署后的服務器整體健康狀況。一些云服務會每分鐘多次調用此狀態頁面,如果服務器無法響應,則會從負載平衡器中移除該服務器。如果您的狀態頁面在此測試中執行查詢,這可能會迅速消耗您的數據庫。

可以想象,在啟動時測試數據庫連接至關重要。但是,一旦服務器成功部署,有效的數據庫連接以后突然變為無效的可能性就很小。我發現最好將成功的結果緩存一小段時間,比如 30 秒。這意味著我的健康檢查仍然可以將有問題的服務器排除在輪換之外,但不會使數據庫過載:

public  static DateTime LastCheckTime = DateTime.MinValue; 
public const int SECONDS_FOR_RETEST = 30 ;

public static bool Status ()
{
var now = DateTime.UtcNow;
var timeSinceLastCheck = now - LastCheckTime;
if (timeSinceLastCheck.TotalSeconds > SECONDS_FOR_RETEST) {
...在這里做一些數據庫健康檢查 ...
LastCheckTime = now;
}
return true ;
}

錯誤3:使用過多查詢進行 API 驗證

大多數重度 API 用戶會迅速發出大量請求。對于每個請求,服務器需要檢查用戶是否經過身份驗證,以及他們是否有權執行他們請求的工作。許多這些檢查都需要從數據庫中提取數據:

對每個請求都這樣做似乎很自然,但這些信息可能會浪費大量時間。幸運的是,有一種 方法可以解決緩慢的身份驗證數據庫查詢問題 :如果調用者發出請求,您可以在短時間內緩存他們的憑據。

緩存授權可能看起來很可怕,因為更改不是即時的,但在實踐中,“即時”很難定義。如果在撤銷訪問權限之前 API 調用正在進行中,則用戶可能會或可能不會根據隨機運氣發出請求 — 無論 API 調用是否在撤銷之前到達。

如果我們更新文檔,說“更改用戶權限后,請等待 5 分鐘,所有服務器才會更新新權限”——那么您就可以規劃性能了!這里的技巧是對 API 調用的承載令牌及其 IP 地址進行哈希處理,然后在緩存中查找所有身份驗證和授權數據:

錯誤4:循環查詢的對象關系映射器

Entity Framework 等現代技術使得訪問數據庫變得極其簡單。事實上,這非常容易,以至于我們經??梢跃帉懸粋€方法來執行數據庫調用 — 然后發現人們在使用這個方法時并沒有意識到它接觸了數據庫。

一個簡單的例子可能是這樣的:
公共 異步任務 < int > GetNumberOfUsers ( int id ) {
var count = 0 ;
var items = await _database.GetRecords(id);
foreach ( var item in records) {
count += CountUsersPerItem(item);
}
返回count;
}

這段代碼可能看起來微不足道,但如果該方法 CountUsersPerItem 聯系數據庫,可能是為了獲取一個標志或查詢一個子表,您可能會發現看似一個查詢變成了數百或數千個查詢。

更糟糕的是,此功能的性能在開發人員的桌面上可能看起來不錯,但當現實世界的客戶面臨同樣的情況時,可能會突然下降。

我發現了一些有助于追蹤此問題的技巧:

錯誤5:因為速度快而忽略查詢

這個問題非常隱蔽?,F代數據庫技術非常強大,簡單的數據庫查詢通??梢耘c查詢 REDIS 一樣快甚至更快。在本地工作的開發人員通常會看到非常好的性能,因為他們的應用程序和數據庫服務器之間沒有延遲,兩者都在筆記本電腦上的容器中運行。

即使您的 SQL Server 或 Postgres 實例可以在一毫秒內做出響應,這些毫秒也會累積起來。如果您的 API 請求發出十個一毫秒的查詢,則可能會使您的 API 延遲增加十毫秒 – 當平均預期時間少于一百毫秒時,這是一個不可忽略的量。

這里的關鍵經驗是,在應用程序接口設計中,每個數據庫查詢都很重要。關注它們,你的應用程序接口就會變得快速而實用。

原文鏈接:https://medium.com/tedspence-com/five-common-database-performance-mistakes-in-api-development-06d99c001bb2

上一篇:

Python調用IP地址API查詢國家信息

下一篇:

在 Spring Boot 中構建 API 響應的最佳方法
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費