接口的命名。前端
請求參數。mysql
支持的協議。nginx
TPS、併發數、響應時長。程序員
數據存儲。DB選型、緩存選型。web
是否須要依賴於第三方。redis
接口是否拆分。sql
接口是否須要冪等。數據庫
防刷。json
接口限流、降級。後端
負載均衡器支持。
如何部署。
是否須要服務治理。
是否存在單點。
接口是否資源包、預加載仍是內置。
是否須要本地緩存。
是否須要分佈式緩存、緩存穿透怎麼辦。
是否須要白名單。
當咱們設計接口,咱們或多或少都會有上面列舉的一些考慮,咱們只有想的更多才能讓讓咱們的接口更加完善,我我的以爲100%完美的接口是不存在,只有適合纔是最重要。
原則一:必須符合Restful,統一返回格式,約定業務層錯誤編碼,每一個編碼能夠攜帶可選的錯誤信息。
原則二: 命名必須規範、優雅。
原則三:單一性。
單一性是指接口要作的事情應該是一個比較單一的事情,好比登錄接口,登錄完成應該只是返回登錄成功之後一些用戶信息便可,但不少人爲了減小接口交互,返回一大堆額外的數據。
好比有人設計一個用戶列表接口,接口他返回每一條數據都是包含用戶了一大堆跟另外無關的數據,結果一問,原來其餘無關的數據是他下一步想要獲取的,想達成數據的懶加載。
原則四:可擴展。
接口擴展性,是指設計接口的時候多想一想多種狀況,多考慮各個方面,其實我以爲單獨將擴展性放在這裏也是不妥的,感受說的跟單一性有點相反的意思,其實這個不是這個意思。
這邊的擴展性是指咱們的接口充分考慮客戶端,想一想他們是如何調用的,他要怎樣使用個人代碼,他會如何擴展個人代碼,不要把過多的工做寫在你的接口裏面,而應該把更多的主動權交給客戶程序員。
如獲取不一樣的列表數據接口,咱們不可能將每一個列表都寫成一個接口。 還有一點,我這裏特別想指出來的是不少開發人員爲了省事(姑且只能這麼理解),將接口設計當成只是 app 頁面展現。
這些人將一個頁面展現就用一個接口實現,而不考慮這些數據是否是屬於不一樣的模塊、是否是屬於不一樣的展現範疇、結果下次視覺一改,整個接口又得重寫,不能複用。
原則五:必須有文檔。
良好的接口設計,離不開清晰的接口文檔表述。文檔表述必定要足夠詳細
原則六:產品心。
爲何我說要有產品心?由於我以爲不少人忽略了這一點。我來講一下假如開發一個app,若是一開始連個交互文檔給你都沒有的話,你怎麼設計接口?
因此我以爲做爲一個服務端後臺開發人員應該要有產品心,特別是對於交互文檔應該好好理解,由於這些都會對咱們的接口設計有很大的影響。
我在設計接口的時候就很常發現不少交互文檔根本就走不通,產品沒有考慮到位,交互文檔缺失,這時候做爲一個開發要主動推進,完善。
原則七:第三方服務接口數據能緩存就緩存。
原則八:第三方服務須要作降級。
原則九:建議消除單點。
原則十:接口粒度要小。
原則十一:客戶端能處理的邏輯就不要給服務端處理,減小服務端壓力。
原則十二:資源預加載。
原則十三:不要過分設計。
原則十四:緩存儘可能不要穿透。
原則十五:接口能緩存就緩存。
原則十六:思辨大於執行
上面也列舉不少須要考慮和設計的原則,其實還有不少方面,我這邊也不是特別全面。
居於上面列舉的這些考慮點,其實這邊說服務是更恰當,能把上面說的點作好,其實接口也是比較可靠,如何設計以及保證接口的高可用和高性能。能夠思考一下如下幾個 point
高性能:若是咱們發現這個接口tps和響應時間沒有達到咱們的要求怎麼辦。
A:數據存儲方面:咱們會想數據庫有沒有分庫、分表、有沒有作主從,有沒有讀寫分離、字段是否有加索引、是否存在慢 sql,數據庫引擎是否選用合適、是否是用了事務;
其次咱們會想到是否是引用了分佈式緩存、緩存 key 大小是否合適,失效時間是否設置合理,會不會大量緩存穿透、有沒有引入本地緩存。
B:業務方面:是否有大量的計算、可否異步處理。是否須要引入線程池或者 MQ 來異步處理任務。有沒有必要將接口進行垂直拆分和水平拆分、將接口粒度變小。
C:其餘方面:nginx 層面作緩存、加機器、用 ssd,資源放 cdn,多機房部署、資源文件預加載。
高可用:如何保證服務高可用,須要從幾個維度來實現:
A:消除單點,基於高可用第二位。
B:能作集羣的所有作集羣。譬如 Redis 集羣、mysql集羣、MongoDB副本集。
C:能作讀寫分離的都作讀寫分離。
D:異地多機房部署,接入 GSLB
E:必須有限流、降級機制。
F:監控。高可用的保證,基於第一位。
下圖是從一個基本的請求出發來梳理須要涉及到各個段,以及各個端能作的事情。談談接口服務,但不侷限於接口自己。
客戶端:資源預加載、限制請求、數據上報。我這邊就拿客戶端來舉個例子。接口服務所依賴的資源包或者一些公共配置預加載在本地,減小接口的交互,經過請求配置文件是否更新,code是不是304等來;
接口作一些請求限制,好比搶紅包、搶券等,單位時間內N次點擊只請求一次等;接口失敗數據上報來;這就是客戶端能夠作到的對接口有幫助的事情
GSLB/HttpDNS:多機房部署、流量切換、域名劫持,通常技術和業務比較成熟的公司這一層。
資源文件放CDN。
負載均衡器:lVS+Nginx是互聯網經常使用的作負載均衡,能夠實現四層/七層負載均衡;這裏除了能夠分流、轉發之外,咱們用的更多的基於令牌桶限流、緩存。
本地緩存。本地緩存能減小咱們訪問DB或者分佈式緩存,本地緩存推薦使用guava,guava裏面有不少特性很好用,例如基於令牌桶的限流;當緩存失效時只穿透一個請求去訪問後端。
線程池。
模塊拆分。將一個項目按功能模塊拆分,一個接口也能夠按業務粒度進行拆分。
數據中心。提供數據支撐,譬如黑名單。
數據庫。加索引、分庫、分表、讀寫分離
分佈式緩存。數據分片、拆分大key,並作集羣,採用分佈式鎖
MQ。作接口拆分利器,異步操做。
其餘服務。限流、防刷以及降級(特別是第三方服務,保證第三方服務down掉不要影響咱們自身的服務)。在這裏也須要考慮作第三方數據的緩存或者持久化,譬如實名認證、身份證認證等。
監控。監控永遠是必須的,能讓你第一時間知道接口服務是否ok
1)接口Restful,統一返回格式,約定業務層錯誤編碼,每一個編碼能夠攜帶可選的錯誤信息
在前司,客戶端和服務之間是有統一的數據返回格式,約定各層的編碼,能夠經過編碼位數以及編碼就能夠看出是那一層出問題。
我以爲這對咱們定位問題以及維護來講具備莫大的意義,並對異常也進行捕捉,封裝成對應的 code,我以前閱讀一些人的代碼發現其項目根本沒有作這一層,由於簡單而不作我以爲有失所望。
2)採用 hybird 模式
採用 hybird 模式涉及到資源預加載的問題,在不少項目裏面都大量使用,譬如前司的生活服務,就採用了 hybird 模式,先將資源文件(包含圖片、前端頁面)打包放到服務器並經過版本號進行管理,並經過一個總的配置文件來管理,若是是H5頁面能夠進行模板預先設計,down到本地。
配置文件格式:
*文件1* name:xxx url:http:xxxx md5:xxxx *文件2* name:zzz url:http:zzzz md5:zzz
客戶端每次啓動應用或者定時請求總的配置文件,經過http code是不是304判斷是否須要下載這個總的配置文件,若是code是200,那麼下載這個配置,比較那個文件發生變化,並將其下載。這樣的好處:
減小接口的交互;
資源預加載,節省流量,打開頁面更加流暢,對於服務端來講字須要返回數據json串就行,而不須要其餘,減小服務端壓力;
方便開發人員,資源管理更加簡潔,好比作活動須要的h5頁面,只須要前端上傳對應的h5資源包到服務端,不須要經過後端開發人員就能夠搞定。
雖然這個原理很簡單,可是如今不少app仍是沒有作這個,都是經過填寫一個url,加載網頁的方式去打開,體驗性太不友好。
3)客戶端
客戶端跟服務端就是接口請求的關係,不少時候須要要求客戶端作一些數據緩存的工做以及一些檢驗工做。在前司已經好幾回給客戶端的同窗坑過了,客戶端同窗接口亂調用,死循環調用。
一次是作一個關於事件提醒的功能,須要天天定時調用調用服務端一個接口,結果客戶端的同窗寫了一個 bug 致使請求每隔一兩秒就調用一次,致使服務器這邊此接口 pv 翻了N倍,並且這個 bug 經過測試同窗很難測試出來;
還有一次發現服務端一段時間之後 UV 不見漲,可是PV卻漲的很猛,定位發現是客戶端同窗A圖省事在一個方法裏面調用了N個接口,也就是模板方法。
由於版本更新,同窗B須要作一個新的功能,而後也調用了A同窗的接口致使,從而致使PV上升,其實B同窗徹底不須要調用這麼多接口。這些都是真實案例,因此這裏須要有一個監控接口異常的機制。
4)思辨大於執行
寫到這裏以爲這個很是重要,思辨大於執行,意味着咱們不是一股腦就去幹,也不是不去幹,咱們作事情須要思考、辨別;從而讓事情更高效、更好、更有力的執行。接口設計也同樣,須要咱們去思辨。
5)本地緩存、分佈式緩存以及異步
緩存在前司主要分爲客戶端緩存、CDN緩存、本地緩存(guava)、Redis緩存。
在MZ早期是接口是採用 DB+本地緩存的方式提供數據,但這種模式DB壓力大,接口吞吐量小,本地緩存多機難一致性、更新不及時問題。
爲了解決這些問題,引入分佈式緩存,並經過 Task 將業務數據刷到 Redis,接口只訪問 redis,不會訪問 DB,及時 DB 故障也不會影響功能。
不一樣的業務系統系統經過 MQ 來解耦,多機房不是經過 MQ 來實現數據的一直。
好比,評論,先經過寫 Redis,寫 MQ 來實現數據在多機房同步,再經過 task 將 Redis 中評論同步到 DB 中。
接口設計涉及方方面面,這邊也只談到一個大概,雖然有點泛泛而談,但願此拙文對你有所啓示。
6)數據庫
數據庫分庫分表,通常都是經過 userId 或者 imei 或者 mac 地址來分表,單表數據量控制在500w之內,這須要咱們提早估算好數據量,儘可能避免數據的遷移。
在前司,數據庫通常都是採用 mysql+MongoDB 兩種,MySQL存儲用戶的用戶數據,MongoDB 存儲業務數據,就像閱讀和生活服務裏面的業務數據就存儲在 MongoDB 裏面。
在數據庫這層,咱們主要也是經過主從模式、讀寫分離、分庫、分表來實現數據的可用性。
7)業務
業務儘量拆分、獨立部署、將項目按業務劃分、按功能劃分等。譬如生活服務,咱們當時主要拆分紅管理後臺 admin、任務 task、活動、web、數據展現模塊。
8)數據中心
每一個大一點的公司都有數據部門,咱們這邊能夠經過數據中心的數據分析來達到咱們須要的數據。
好比黑名單,推廣效果、活動數據。咱們能夠經過這些完善咱們的接口功能。以前在前司作了個數據處理後異步加載到 Redis 來實現數據利用的項目。