內容來源:2017年5月13日,一條架構師管凱強在「Java開發者大會 | Java之美【上海站】」進行《API網關的設計思路及落地》演講分享。IT大咖說做爲獨家視頻合做方,經主辦方和講者審閱受權發佈。
閱讀字數:2640 | 4分鐘閱讀
API網關是一個服務器,是系統的惟一入口。從面向對象設計的角度看,它與外觀模式相似。API網關封裝了系統內部架構,爲每一個客戶端提供一個定製的API。html
嘉賓演講視頻和PPT地址:t.cn/R9DZZ0h前端
移動互聯時代迭代速率對於後端開發帶來了一些挑戰。後端
在咱們公司的商品詳情頁上,包含了商品信息、價格信息、促銷信息和推薦列表四個部分。設計模式
在開發過程當中,咱們想要把這四個信息在一個接口訪問中所有吐出來,嘗試給出一個萬能接口。緩存
事實上,咱們在第一次這樣作的時候或許是靠譜的,可是當產品發生變動的時候,好比產品想把推薦列表換成熱銷榜,那麼以前作的萬能接口就已經不知足這個業務場景了,只能新開一個V2版本。安全
這樣重複必然會致使接口的膨脹以及維護成本愈來愈高。服務器
因此雖然咱們都在追求一個萬能的解,但這個「解」也許並不存在。網絡
咱們商品詳情頁的數據來自於商品系統、價格系統、推薦系統和營銷系統。而對於客戶端或用戶而言,其實沒有必要知道每一個接口由哪一個微服務提供的,只需獲得數據便可。架構
因此咱們面臨的問題就是怎樣避免讓客戶端感知微服務邊界的存在,不一樣的後端、前端團隊須要統一的接口設計、接入規範。app
API網關是擋在全部微服務以前的一個透明層,是請求進入系統的惟一節點。基於這一點,一方面解決了對調用方隱藏微服務的系統邊界問題,另外一方面負責服務請求路由及協議轉換。它可能還具備其它職責,如身份驗證、權限控制、負載均衡、「請求整形」與管理。
在咱們的APP和WEB上,全部請求都基於HTTP,RPC服務是基於DUBBO的RPC框架來作。
API網關作的最簡單的一件事就是可以讓用戶發起的請求經過API網關轉成對RPC服務的調用,再回到用戶的APP上。
主要解決了HTTP請求到RPC調用實例的映射,以及把無類型的參數轉換爲帶類型的參數。
實現了一個輕量級的MVC框架,將請求轉換爲對RPC實例的調用。
我認爲一個設計良好的接口必定包含了明確的異常編碼,以及這個異常編碼在什麼業務場景上出現,這個異常編碼怎樣在客戶端獲得合適的處理。
還須要有一個明確的調用權限說明,和清晰的參數列表、返回結果。
如圖,這上面有一個ApiGroup,來描述業務模塊的屬性。
這是咱們某個特定的方法,和control有些類似。包含了API的方案名、SecurityType是權限認證的level。
Designed ErrorCode是用來對客戶端接口明確報出異常。
入參描述有ApiAutowired和ApiParameter兩種類型。
在API註冊流程中,咱們首先作了ApiParser,用於解析API信息,解析完以後會獲得接口的完備信息,包含了接口的描述及整個業務異常編碼的描述。
第二步是要建立一個RPC調用實例,也就是RpcInvoker。
接下來須要建立一個服務的動態代理,來解決無類型參數到RPC接口上的有類型參數的轉換。
最後是把proxy作一個緩存。
這是一個動態生成proxy的例子。
咱們用ASM字節碼框架在運行期動態生成proxy。圖中函數是把string類型參數轉換爲強類型參數。
第一步解析請求,在URL中須要描述清楚HTTP調用哪些接口,解析請求就是要pass出這些信息。
而後要作安全驗證,以保證什麼樣的請求才能夠被路由到微服務的請求。
第三步構建API調用的上下文。上下文裏包含了用戶ID等信息,這些信息來自於用戶訪問令牌解密以後。
接下來就是作代理的執行,最後對結果作序列化。
作安全策略的大致上的處理方法就是設備識別、數字簽名,也包括HTTPS。
設備識別主要是用於確認身份,依賴於一個叫token的訪問令牌來作。
在APP上用戶若是發起了登陸,首先通過網關,而後到用戶服務,登陸完成後下發appSecret和token。
APP在調用API以前要作數字簽名,須要一個簽名的密鑰,也就是下發的appSecret。
API到了網關,網關能夠解析出用戶身份對應的appSecret,因此它能夠驗證這個請求是否是正常的請求。驗證經過後就到了業務系統。
中間人攻擊是在APP發起請求離開設備之後,在網絡傳輸過程當中若是被第三方竊聽,它會去嘗試篡改請求。
中間人竊取到網絡傳輸中的請求報文,雖然得到了token等關鍵信息,但因爲簽名密鑰appSecret沒法經過監聽網絡請求得到,因此中間人篡改請求卻沒法獲得一個正確的數字簽名。
雖然萬能接口是不存在的,但咱們嘗試實現減輕一個接口中同時返回來自於不一樣微服務的信息的需求。基於這個需求,咱們在API網關擴展出一個組合式調用的協議。
簡單來講,這個協議是在一次HTTP請求中對RPC服務發起屢次調用,在API網關作響應報文的整合,最後作返回。
用Façade設計模式爲多個RPC服務的接口作了Façade,在Façade上把API作組裝,統一暴露給客戶端,讓API網關成爲API的Façade。
但咱們以前嘗試作的萬能接口跟不上需求的變化,最終它帶來的惡果就是代碼難以維護。若是在API網關上去不停地爲接口作Façade,API網關的代碼必然也是很難維護的。
爲了解決這個問題,咱們讓客戶端去定義Façade,API網關只負責組裝。
使用異步並行方式,將組合式調用串行變並行。
首先是請求前置處理,實際調用則採用了dubbo async調用,是dubbo原生的調用方式。最後作請求後置處理。
可是Dubbo異步調用標識會經過attachment向下傳遞,污染調用鏈,致使後續調用鏈路都變成了異步方式。並且dubbo filter鏈機制在異步調用中具備侷限性。
這兩個問題都是最後改了dubbo的源碼來解決的。
提供在線API文檔和接入SDK。
可是變化老是存在,咱們該如何解放生產力呢?
擴大API的影響力,基於API信息生成敏捷開發工具;強類型約束的SDK,及時暴露違背「契約」的行爲。
這是咱們作的一些敏捷開發的工具。
這是在線文檔工具和調試工具。
Dubbo attachment是一種隱式傳參機制,具備傳遞性。
基於這個機制能夠把請求標識在調用鏈路上一直作傳遞,調用鏈路上增長AOP、向日志上下文中傳遞traceid。
在API網關落下的全部請求日誌都會有相應的錯誤編碼,能夠作zabbix基於這個服務的遠程報錯。
從技術設計的角度上來講,API是一種抽象,它隔離了咱們的使用以及實現;從開發管理的角度上來講,API是一種契約。
API網關是一種微服務的架構解決方案,服務於API「契約」精神,並儘量的擴大這種契約的影響力,構建一種圍繞API開發的「生態」。
API網關前面是HTTP的傳輸,在這過程當中不必定須要中心化的存儲,能夠嘗試用CDN來作邊界緩存。
熱發佈服務於全部微服務,微服務接口的變動怎樣作到熱重啓,是一個比較有挑戰性的事情。
咱們以前作的事情只是日誌定位,談不上調用鏈路跟蹤,調用鏈路跟蹤有更專業的解決方案。
API網關目前作的只是權限驗證,尚未和風控系統結合起來。
限流降級也尚未作。
在網關上作ab測試會是比較有意義的。
我今天的分享就到這裏,感謝聆聽!