API設計中性能提升的十個建議
節前的時候, 一好友約我聊一聊API 的設計。當時覺得仿佛有萬語千言,但我又難以脫口而出1、2、3。原來,即便是工作的日常,也缺乏一個系統性的思考和整理。API的設計涉及到的方面很多, 分類是一個基本的思考方式。如果可以形成一個系列性的文字,那就從性能開始吧。
就像任何性能一樣,API 性能主要取決于如何響應不同類型的請求。例如:典型的電商場景,顯示用戶當前的訂單。應用程序從一個 API 獲取訂單詳情。但是,如果希望用戶在一個地方能查看他們所有的訂單,這意味著,我們的 API 現在將返回比以前更多的數據,后臺的負載會更大。如何確保我API 能夠將所有數據返回給用戶,而不會出現延遲、服務器錯誤和過多請求等問題呢?
一般地, 如何在API設計中提升性能呢?還沒有梳理出完整的方法論,但就REST API 而言,根據多年的經驗和教訓,這里總結了10點建議。
1.啟用日志,建立監控
API 的監控是最重要的,沒有之一。
擁有日志、監控和告警可以幫助我們在潛在問題變成真正問題之前診斷并糾正問題。如果沒有啟用日志記錄,并且存在潛在問題,那么我們將無法跟蹤性能指標,或者在特定請求中定位問題發生的位置。奢侈一點的話, 要嘗試全鏈路跟蹤系統,盡管成本較高,但物有所值。
2.提升網速,帶寬足夠
即便API設計的性能非常強大,也扛不住緩慢的網絡延遲。不可靠的網絡可能會導致宕機,導致違反SLA、服務條款以及曾經向客戶做出的承諾。必須要投資適當的網絡基礎設施,以便我們能夠維持所需的性能水平,有時候,可以通過利用和購買足夠的云資源來實現。
3.減少有效負載
如果響應數據的有效負載非常大,將會減慢請求完成的時間,并影響性能。簡單地,使用 GZip 壓縮來減少有效載載的大小,可以在 Web API 上使用 Deflate 壓縮,或者,可以將 Accept-EncodingRequest 更新為 gzip。有效的數據壓縮減少了在 web 應用程序上響應的下載量,同時提高了上傳速度。
4.使用緩存
緩存是提高 API 性能的最簡單的方法之一。如果有經常返回相同響應的請求,那么該響應的緩存有助于避免額外的服務調用和數據庫查詢。需要注意的是,確保在緩存使用的生命周期,尤其是在發生數據更新的時候。緩存增強了可伸縮性。服務端可以通過設置響應頭來提高緩存能力,比如 Cache-Control、 Expires、 Pragma、 Last-Modified 等等。
5.流控與頻控
API 遭受 DDoS 攻擊是惡意的,但有時候,也可能是工程師無意造成的,例如當工程師在某個本地應用程序的循環中執行調用 API 的調用。一般地,可以通過監視每個 IP 地址或每個 SSO令牌發生的事務數量來避免這種情況。頻控和流控都是為了性能而實現限速的方式,有助于處理API的意外調用,并主動監視和識別可能的惡意活動,也是實現安全性的重要手段。
6.嘗試HTTP 的標準方法
嘗試使用HTTP 的標準方法,對API 的性能會有一定的幫助。
http 方法 | 冪等性 | 是否安全 |
get | 是 | 是 |
head | 是 | 是 |
put | 是 | 否 |
delete | 是 | 否 |
post | 否 | 否 |
patch | 否 | 否 |
例如,PUT 和 PATCH 操作在更新資源方面是相似的,但執行更新的方式是不同的。PUT 操作通過向整個資源發送更新來更新資源。PATCH 操作只對需要更新的資源應用部分更新。由此產生的 PATCH 調用可以產生更小的有效負載,從而提高性能。需要注意的是PATCH 調用可不是冪等的。
7.嘗試標準的HTTP 狀態碼
我們可以進一步對響應進行標準化、細分和限制,這有助于降低結果的復雜性,并通過僅針對客戶所要求的內容提供響應/結果來改善整個客戶體驗。嘗試使用標準的HTTP 狀態碼是一種不錯的方式,顯然,響應的狀態由其狀態代碼指定: 1xx 表示信息,2xx 表示成功,3xx 表示重定向,4xx 表示客戶機錯誤,5xx 表示服務器錯誤。例如,使用 HTTP狀態碼,并且只使用響應體提供錯誤細節。
HTTP/1.2 400 Bad RequestContent-Type: application/json{ "error": "Expected xxx in xxx"}
8.動靜分離,使用CDN
此外,如果有大量的后臺進程進程,可以在單獨的線程上運行這些進程,以避免阻塞請求。常見的一種方式是將API請求中的靜態資源分離開了,可以使用內容交付網絡(CDN)來更快地服務不同地區請求中的靜態資源。
9.啟用分頁,過濾排序
對于大型數據集,限制返回的數據量是至關重要的。此外,可能希望指定要包含在響應中的資源的字段或屬性,從而限制返回的數據量,最終希望查詢特定的值并對返回的數據進行排序。
分頁有助于從多個響應創建大量的內容。這種優化有助于改進響應,同時保存傳輸/顯示給客戶的數據。當鏈接在響應中返回時,api 變得更具自我描述性。對于在支持分頁的響應中返回的集合,“ first”、“ last”、“ next”和“ prev”鏈接至少是有益的。
10.使用性能更優的應用框架
應用框架的使用是為了提高開發效率,如果為了性能進行適當的優化和增強,也可以為業務和客戶提供極其強大的體驗。一些框架專門用于構建 REST API,可以幫助我們在不犧牲生產力的前提下提升性能。例如,在python中,web 應用框架眾多,例如 Django ,Flask,Tornado,Falcon等等。就性能而言,Falcon和Tornado可能是不錯的選擇。在 Node 中,Restify 似乎也不錯的選擇,但是我還沒有在生產環境來嘗試它,基于Go 語言的應用框架更是非常值得關注的。
總之,業務需求和客戶期望總是隨著時間而變化的,我們有責任決定如何以高效的方式構建高性能的API,這樣可以幫助我們實現并超越目標。根據特定的 API 和用例,確定API與什么服務交互,以及調用的頻率,從哪里調用等等,我們可以用不同的方式實現高性能的API。