記得去年面試電商的移動(dòng)端架構(gòu)師職位時(shí),被問(wèn)過(guò)一個(gè)問(wèn)題:“當(dāng)我們的app存在多個(gè)版本,1.1,1.2,1.3,2.0,2.1,2.1時(shí),設(shè)計(jì)系統(tǒng)架構(gòu)滿足不同用戶不同版本的app同時(shí)可以使用,這個(gè)問(wèn)題如何思考?”
我并沒(méi)有實(shí)際遇到過(guò)這樣的情況,我一直工作在傳統(tǒng)軟件公司,多數(shù)傳統(tǒng)軟件公司只有一個(gè)答案,強(qiáng)制升級(jí)api和app版本才可以使用。所以這個(gè)問(wèn)題當(dāng)時(shí)我并沒(méi)有回答的很好。這件事情過(guò)去很久了,最近在看一本書“iOS網(wǎng)絡(luò)高級(jí)編程”,其中一句話“設(shè)計(jì)良好的api可以適應(yīng)靈活的變化”,引起了我的 一些思考,其實(shí)這個(gè)問(wèn)題很簡(jiǎn)單。如果再問(wèn)一次上面的問(wèn)題,我會(huì)這么回答。
首先,對(duì)于兼容多版本app這個(gè)問(wèn)題,解決的核心方向在于服務(wù)端api的多版本管理,api首先要有v1.1,v1.2 … ,(這些版本并不一定需要和app有一一對(duì)應(yīng)關(guān)系),這樣不同版本的app調(diào)用對(duì)應(yīng)的api,就可以滿足多版本app同時(shí)可以使用的問(wèn)題。調(diào)用的方式可以直接寫在代碼中,復(fù)雜寫的情況也可以使用服務(wù)定位器。
接下來(lái)考慮服務(wù)端api的多版本設(shè)計(jì),主要有2種方案: - 1:同一套代碼,兼容不同版本的api。根據(jù)請(qǐng)求中的版本信息區(qū)分,返回不同的數(shù)據(jù)。 - 2:嚴(yán)格區(qū)分個(gè)版本api的代碼,使用不同的分支或是tags,分布部署不同版本api對(duì)應(yīng)的服務(wù)
方案1的優(yōu)點(diǎn)在于簡(jiǎn)單,缺點(diǎn)在于容易造成代碼混亂,產(chǎn)生bug。
方案2是我比較推薦的,使用git的tags進(jìn)行api版本管理,每個(gè)api單獨(dú)部署,邏輯清晰代碼易于維護(hù),還能減少單個(gè)節(jié)點(diǎn)的負(fù)載壓力。
其他的思考
如何設(shè)計(jì)出優(yōu)雅的多版本api接口?這個(gè)問(wèn)題在于通過(guò)什么方式傳遞api的版本號(hào)數(shù)據(jù),主要有這么幾種
1:api版本號(hào)放在url路徑中www.xxx.com/v1.api.xxx
2:api版本號(hào)放在url參數(shù)中api.xxx.com/api?version=v1&..
3:api版本號(hào)放在請(qǐng)求的header中
4:api版本號(hào)放在二級(jí)域名中。v1.api.xxx.com
因?yàn)橹拔彝扑]的是方案2,分開(kāi)部署,所以更傾向于選4。
遠(yuǎn)程門面模式
對(duì)于一個(gè)應(yīng)用來(lái)說(shuō),可能會(huì)涉及到一些第三方的接口,那么這些第三方的api接口為了滿足api的多版本設(shè)計(jì)(第三方的api接口也會(huì)常常有所變動(dòng)),可以考慮使用遠(yuǎn)程門面模式,即app不直接訪問(wèn)第三方的api,而是通過(guò)服務(wù)端api簡(jiǎn)介訪問(wèn)第三方api。
舉個(gè)例子,如果app中需要得到城市的氣象數(shù)據(jù),氣象數(shù)據(jù)是一個(gè)第三方公司提供的,那么app不應(yīng)該直接訪問(wèn)第三方的接口,而是通過(guò)api從自己的服務(wù)端獲取數(shù)據(jù),自己服務(wù)端通過(guò)調(diào)用第三方接口獲取氣象數(shù)據(jù)。
這樣做的好處很明顯。
1:第三方的api可以納入版本管理,并且在第三方接口變動(dòng)時(shí),課通過(guò)修改api來(lái)應(yīng)對(duì),免去修改app導(dǎo)致重新審核的問(wèn)題
2:保證接口的穩(wěn)定性和統(tǒng)一性(比如api的接口是rest json,但是第三方的接口有可能是xml,soap等,這樣可以通過(guò)服務(wù)端統(tǒng)一封裝接口,而app統(tǒng)一調(diào)用api的rest json接口)
3:簡(jiǎn)化客戶端邏輯和代碼,這個(gè)符合客戶端盡可能輕的開(kāi)發(fā)準(zhǔn)則
維護(hù)多少個(gè)版本比較合適
如果維護(hù)的app或者說(shuō)是api版本過(guò)多,必然會(huì)導(dǎo)致維護(hù)成本大大提高。我們應(yīng)該在在api端統(tǒng)計(jì)每個(gè)版本的使用量,把使用量較少的api版本給干點(diǎn)。另一方面,一些過(guò)時(shí)的api我們也并不希望用戶繼續(xù)使用時(shí),也可以考慮強(qiáng)行干掉,對(duì)于app端使用了一些被干掉的api可以提出用戶升級(jí)提示 ,用戶可以根據(jù)自己情況選擇升級(jí),如果不升級(jí),其他的api也能夠使用。強(qiáng)制用戶因?yàn)閱蝹€(gè)api升級(jí)客戶端會(huì)造成不好的用戶體驗(yàn),除非這個(gè)api真的值得真么做。
服務(wù)定位器
多版本api策略對(duì)于客戶端來(lái)說(shuō),api請(qǐng)求的地址可以直接寫在app代碼中,也可以通過(guò)服務(wù)定位器,去動(dòng)態(tài)獲取請(qǐng)求服務(wù)的url地址,使用服務(wù)定位器可以使多版本api的策略更加靈活, 可以考慮在每次app啟動(dòng)時(shí)候調(diào)用服務(wù)定位器接口
[{
"name":"v1",
"url":"v1.xxx.com/",
"vsersion":"v1",
"other":"..."
},
{
"name":"v2",
"url":"v2.xxx.com/",
"vsersion":"v2",
"other":"..."
},
{
"name":"天氣服務(wù)",
"url":"weather.xxx.com/",
"vsersion":"v1",
"other":"..."
}]