導語:在Java生態中,我們經常直接或者間接的用到動態代理,比如透過動態代理呼叫遠端服務,再比如透過動態代理實現解耦。本文結合京東服務框架JSF,講述京東使用動態代理進行抽象的一次實踐,以達到升級資料庫訪問層的目的。
劉世傑,京東商城Java高階開發工程師,一直從服務端研發工作,目前主要負責京東海外站商品主資料基礎服務。個人喜歡讀原始碼,註重細節,有些許程式碼潔癖。對高可用、高效能、高併發方面的技術保持持續關註。
1. 背景
最近在做資料庫(MySQL)方面的升級改造。現狀是資料庫同時被多個應用直連,存在了一些問題:
-
有大量的重覆程式碼,維護成本較高,也不優雅;
-
出現SQL陳述句質量的問題無法很快定位到是哪個應用導致的;
-
資料庫呼叫方過於分散,不便於統一控制,比如部分業務資料的讀寫、遮蔽等;
-
業務的發展,有的表資料量已經到了一定的規模,幾百萬到幾千萬不等,資料庫儲存拆分是必須要進行的事情。
解決問題的方式很簡單,就是把各應用中與此業務相關的dao層抽象成為一個單獨應用(以下稱為internal-rpc-app),進行統一管理。
2. 具體實現
具體的業務應用與internal-rpc-app的內部通訊使用公司內部具有服務治理功能的RPC框架JSF,JSF是一款穩定高效的框架,它對服務治理的粒度是介面,介面透過Spring做服務的釋出和呼叫配置。每個介面對應一個資料表的CURD及特殊業務。
2.1 標準版本 1.0
2.1.1. 介面註冊申請
註冊介面: com.jd.xx.BizRpcService1
註冊介面: com.jd.xx.BizRpcService2
註冊介面: com.jd.xx.BizRpcService3
……
註冊介面: com.jd.xx.BizRpcServiceN
2.1.2. 服務提供方配置
……
2.1.3. 客戶端呼叫方配置
……
2.1.4 小結
此版本實現了我們的最初的目的,但是有一個不太好的地方,就是配置的工作量太高,前面有說到JSF框架的治理維度是介面。這也意味著,每次新增介面都要提交申請操作,同時要在consumer和provider做相對應的配置,幾個還好,如果資料表有幾十個上百個,重覆的工作量就很大。同時內部介面也不需要做太細粒度的服務治理。於是有了第二版,主要目的是簡化大量重覆配置。
2.2 最佳化呼叫體驗版本2.0
2.2.1 內部實現 – 客戶端
首先定義呼叫API:
BizRpcService1 bizRpcService1 = InternalPrxoyServices.BizRpcService1;
bizRpcService1.method1(param1, param2);
InternalPrxoyServices關鍵程式碼:
BizProxyRpcService1關鍵程式碼:
BaseProxyService關鍵程式碼:
InternalRpcService介面定義:
2.2.2 內部實現-服務端
服務端實現比較簡單,直接根據介面傳過來當serviceName、methodName、objects即可定位到具體service到方法,直接執行即可。
2.2.3 小結
到這裡,我們透過靜態代理實現了具體的標的,透過實現具體的介面類。我們不再需要定義過多的配置了,客戶端呼叫也變得簡單明瞭。
那麼,結束了嗎?並沒有,在解決了大量配置的問題的同時,因為要寫大量的代理類,又引入了新的工作量。
2.3 最終版本3.0
在這一版,我們很自然的引入了動態生成代理。
2.3.1 客戶端具體實現
因為引入了動態代理,所以要重新改寫InternalPrxoyServices:
ProxyServiceFactory關鍵程式碼:
InternalRpcProxy關鍵程式碼:
2.4 小結
至此,已經解決了2.2.3提到的大量建立代理類的問題。當然我們還做了很多文章中沒有提及的事情,比如:
-
透過宣告哪些介面可以走動態代理
-
方法重名、客戶端介面合法性等校驗
-
將method存入快取
3. 總結
透過建立獨立的應用,解決了前面資料庫被多應用讀寫所產生的問題,透過開發了統一介面解決了服務端和客戶端配置過多的問題。程式碼經過一步步抽象後,最終發現實現了一個簡單的RPC雛形,只不過通訊層是基於公司的JSF框架。這引發了一些框架方面的思考:
-
是否應該去掉人工審批類似的流程?
-
是否應該允許更靈活的釋出服務?比如:根據註解自動掃描釋出服務、根據註解自動獲取服務。
這不是技術問題,而是怎麼權衡的問題。
Java招聘:
我們團隊主要負責京東海外站業務,目前發展快速。團隊氛圍open,領導nice,福利多多。急需Java研發加入我們,初級高階都可。
歡迎傳送簡歷至liujunhua@jd.com;liushijie@jd.com。
相關閱讀:
高可用架構
改變網際網路的構建方式
長按二維碼 關註「高可用架構」公眾號