Edge Service是ServiceComb提供的JAVA網關服務。Edge Service作爲整個微服務系統對外的接口,向最終用戶提供服務,接入RESTful請求,轉發給內部微服務。Edge Service以開發框架的形式提供,開發者可以非常簡單的搭建一個Edge Service服務,通過簡單的配置就可以定義路由轉發規則。同時Edge Service支持強大的擴展能力,服務映射、請求解析、加密解密、鑑權等邏輯都可以通過擴展實現。
Edge Service本身也是一個微服務,需遵守所有微服務開發的規則。其本身可以部署爲多實例,前端使用負載均衡裝置進行負載分發;也可以部署爲主備,直接接入用戶請求。開發者可以根據Edge Service承載的邏輯和業務訪問量、組網情況來規劃。
開發微服務網關
搭建框架
使用ServiceComb的內置Edge Service邊緣服務
3步完成搭建微服務網關
↓↓↓
•配置依賴關係
在項目中加入edge-core的依賴,就可以啓動Edge Service的功能。Edge Service在請求轉發的時候,會經過處理鏈,因此還可以加入相關的處理鏈的模塊的依賴,下面的實例增加的負載均衡的處理鏈,這個是必須的。
•定義啓動類
和開發普通微服務一樣,可以通過加載Spring的方式將服務拉起來。
•增加配置文件microservie.yaml
Edge Service本身也是一個微服務,遵循微服務查找的規則,自己也會進行註冊。注意APPLICAIONT_ID與需要轉發的微服務相同。在下面的配置中,指定了Edge Service監聽的地址,處理鏈等信息。其中auth處理鏈是DEMO項目中自定義的處理鏈,用於實現認證。同時auth服務本身,不經過這個處理鏈,相當於不鑑權。
定製路由規則
使用Edge Service的核心工作是配置路由規則。場景不同,規則也不同。 路由規則由一系列AbstractEdgeDispatcher組成。Edge Service提供了幾個常見的Dispatcher,通過配置即可啓用,如果這些Dispatcher不滿足業務場景需要,還可以自定義。
•使用DefaultEdgeDispatcher
DefaultEdgeDispatcher是一個非常簡單、容易管理的Dispatcher,使用這個Dispatcher,用戶不用動態管理轉發規則,應用於實際的業務場景非常方便,這個也是推薦的一種管理機制。它包含如下幾個配置項:
常見的這些配置項的示例及含義如下:
•[prefix=rest;withVersion=true;prefixSegmentCount=1]微服務xService提供的URL爲: /xService/v1/abc,通過Edge訪問的地址爲/rest/xService/v1/abc,請求只轉發到[1.0.0-2.0.0)版本的微服務實例。
•[prefix=rest;withVersion=true;prefixSegmentCount=2]微服務xService提供的URL爲: /v1/abc,通過Edge訪問的地址爲/rest/xService/v1/abc,請求只轉發到[1.0.0-2.0.0)版本的微服務實例。
•[prefix=rest;withVersion=true;prefixSegmentCount=3]微服務xService提供的URL爲: /abc,通過Edge訪問的地址爲/rest/xService/v1/abc,請求只轉發到[1.0.0-2.0.0)版本的微服務實例。
•[prefix=rest;withVersion=false;prefixSegmentCount=1]微服務xService提供的URL爲: /xService/v1/abc,通過Edge訪問的地址爲/rest/xService/v1/abc,請求可能轉發到任意微服務實例。•[prefix=rest;withVersion=false;prefixSegmentCount=2]微服務xService提供的URL爲: /v1/abc,通過Edge訪問的地址爲/rest/xService/v1/abc,,請求可能轉發到任意微服務實例。
•[prefix=rest;withVersion=false;prefixSegmentCount=2]微服務xService提供的URL爲: /abc,通過Edge訪問的地址爲/rest/xService/abc,,請求可能轉發到任意微服務實例。
withVersion配置項提供了客戶端灰度規則,可以讓客戶端指定訪問的服務端版本。Edge Service還包含根據接口兼容性自動路由的功能,請求會轉發到包含了該接口的實例。假設某微服務,兼容規劃爲所有高版本必須兼容低版本,部署了以下版本實例:
1.0.0,提供了operation1
1.1.0,提供了operation1、operation2
Edge Service在轉發operation1時,會自動使用1.0.0+的規則來過濾實例
Edge Service在轉發operation2時,會自動使用1.1.0+的規則來過濾實例
以上過程用戶不必做任何干預,全自動完成,以避免將新版本的operation轉發到舊版本的實例中去。
•使用URLMappedEdgeDispatcher
URLMappedEdgeDispatcher允許用戶配置URL和微服務的映射關係。使用它可以非常靈活的定義哪些URL轉發到哪些微服務。它包含如下幾個配置項:
businessV1配置項表示的含義是將請求路徑爲/usr/business/v1/.的請求,轉發到business這個微服務,並且只轉發到版本號爲1.0.0-2.0.0的實例(不含2.0.0)。轉發的時候URL爲/business/v1/.。path使用的是JDK的正則表達式,可以查看Pattern類的說明。prefixSegmentCount表示前綴的URL Segment數量,前綴不包含在轉發的URL路徑中。
有三種形式的versionRule可以指定。2.0.0-3.0.0表示版本範圍,含2.0.0,但不含3.0.0;2.0.0+表示大於2.0.0的版本,含2.0.0;2.0.0表示只轉發到2.0.0版本。2,2.0等價於2.0.0。從上面的配置可以看出,URLMappedEdgeDispatcher也支持客戶端灰度。當然配置項會比DefaultEdgeDispatcher多。URLMappedEdgeDispatcher支持通過配置中心動態的修改配置,調整路由規則。
•自定義Dispatcher
自定義Dispatcher包含兩個步驟:
1.實現AbstractEdgeDispatcher
2.通過SPI發佈:增加文件META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher,並寫入實現類
詳細的代碼細節可以參考下面的章節"DEMO功能說明"。開發者也可以參考DefaultEdgeDispatcher等代碼來定義自己的Dispatcher。
•進行認證鑑權和其他業務處理
通過Edge Servie工作流程可以看出,可以通過多種方式來擴展Edge Service的功能,包括Dispatcher、HttpServerFilter、Handler、HttpClientFilter等。比較常用和簡單的是通過Handler來擴展。DEMO裏面展示瞭如何通過Handler擴展來實現鑑權。詳細的代碼細節可以參考下面的章節"DEMO功能說明"。
工作原理
工作流程
Edge Service的工作流程如下
藍色背景部分在Eventloop線程中執行,黃色背景部分:
•如果工作於reactive模式,則直接在Eventloop線程執行
•如果工作於線程池模式,則在線程池的線程中執行
工作模式
reactive (默認)
Edge Service默認工作於高性能的reactive模式,此模式要求工作於Edge Service轉發流程中的業務代碼不能有任何的阻塞操作,包括不限於:
•遠程同步調用,比如同步查詢數據庫、同步調用微服務,或是同步查詢遠程緩存等等
•任何的sleep調用
•任何的wait調用
•超大的循環
Edge Service的底層是基於netty的vertx,以上約束即是netty的reactive模式約束。
線程池
如果業務模型無法滿足reactive要求,則需要使用線程池模式。
此時需要在Edge Service的microservice.yaml中配置:
這裏的servicecomb.executor.groupThreadPool是ServiceComb內置的默認線程池對應的spring bean的beanId;業務可以定製自己的線程池,並聲明爲一個bean,其beanId也可以配置到這裏。
DEMO功能說明
請參考github上的edge service demo:
https://github.com/ServiceComb/ServiceComb-Java-Chassis/tree/master/demo/demo-edge
該demo包含以下工程:
authentication:微服務:鑑權服務器
edge-service
hiboard-business-1.0.0微服務:business,1.0.0版本,operation add
hiboard-business-1.1.0微服務:business,1.1.0版本,operation add/dec
hiboard-business-2.0.0微服務:business,2.0.0版本,operation add/dec
hiboard-consumer作爲一個普通的httpclient,而不是servicecomb consumer
hiboard-model非微服務,僅僅是一些公共的model
通過edge-service訪問微服務business的不同版本,並確認是由正確的實例處理的。
1.註冊Dispatcher
實現接口org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher,或從org.apache.servicecomb.edge.core.AbstractEdgeDispatcher繼承,實現自己的dispatcher功能。
實現類通過java標準的SPI機制註冊到系統中去。
Dispatcher需要實現2個方法:
•getOrder
Dispatcher需要向vertx注入路由規則,路由規則之間是有優先級順序關係的。
系統中所有的Dispatcher按照getOrder的返回值按從小到大的方式排序,按順序初始化。
如果2個Dispatcher的getOrder返回值相同,則2者的順序不可預知。
•init
init方法入參爲vertx框架中的io.vertx.ext.web.Router,需要通過該對象實現路由規則的定製。
可以指定滿足要求的url,是否需要處理cookie、是否需要處理body、使用哪個自定義方法處理收到的請求等等
更多路由規則細節請參考vertx官方文檔:vertx路由機制https://vertx.io/docs/vertx-web/java/#_routing_by_exact_path
提示:
多個Dispatcher可以設置路由規則,覆蓋到相同的url。
假設Dispatcher A和B都可以處理同一個url,並且A優先級更高,則:
•如果A處理完,既沒應答,也沒有調用RoutingContext.next(),則屬於bug,本次請求掛死了
•如果A處理完,然後調用了RoutingContext.next(),則會將請求轉移給B處理
2.轉發請求
註冊路由時,指定了使用哪個方法來處理請求(下面使用onRequest來指代該方法),在onRequest中實現轉發邏輯。
方法原型爲:
系統封裝了org.apache.servicecomb.edge.core.EdgeInvocation來實現轉發功能,至少需要準備以下參數:
•microserviceName,業務自行制定規則,可以在url傳入,或是根據url查找等等
•context,即onRequest的入參
•path,轉發目標的url
•httpServerFilters,Dispatcher父類已經初始化好的成員變量
edgeInvoke調用內部,會作爲ServiceComb標準consumer去轉發調用。
作爲標準consumer,意味着ServiceComb所有標準的治理能力在這裏都是生效的。
3.設置兼容規則
不同的業務可能有不同的兼容規劃,servicecomb默認的兼容規則,要求所有新版本兼容舊版本。如果滿足這個要求,則不必做任何特殊的設置。
還有一種典型的規劃:
1.0.0-2.0.0內部兼容,url爲/microserviceName/v1/….的形式
2.0.0-3.0.0內部兼容,url爲/microserviceName/v2/….的形式
……
各大版本之間不兼容
此時,開發人員需要針對EdgeInvocation設置兼容規則:
versionMapper的作用是將v1或是v2這樣的串,轉爲1.0.0-2.0.0或2.0.0-3.0.0這樣的兼容規則。
注意:
接口不兼容會導致非常多的問題。java chassis要求高版本服務兼容低版本服務,只允許增加接口不允許刪除接口。在增加接口後,必須增加微服務的版本號。在開發階段,接口變更頻繁,開發者往往忘記這個規則。當這個約束被打破的時候,需要清理服務中心微服務的信息,並重啓微服務和Edge Service(以及依賴於該微服務的其他服務)。否則可能出現請求轉發失敗等情況。
4.鑑權
Edge Service是系統的邊界,對於很多請求需要執行鑑權邏輯。
基於標準的ServiceComb機制,可以通過handler來實現這個功能。
最簡單的示意代碼如下:
Auth表示是鑑權微服務提供的接口,Invoker.createProxy("auth", "auth", Auth.class)是透明RPC開發模式中consumer的底層api,與@ReferenceRpc是等效,只不過不需要依賴spring bean機制。
Auth接口完全由業務定義,這裏只是一個示例。
Handler開發完成後,配置到edge service的microservice.yaml中:
這個例子,表示轉發請求給所有的微服務都必須經過鑑權,但是調用鑑權微服務時不需要鑑權。
文末小結
本文向社區讀者從使用角度闡述了使用Edge Service做邊緣服務。
我們也非常歡迎愛好者們向社區提問和貢獻代碼。
下章我們將介紹ServiceComb+Zipkin使用篇。
如果在閱讀代碼時有任何疑問想交流,歡迎掃碼加入進微信羣。
期待志同道合的朋友們加入
ServiceComb的大門爲你們敞開~
用心做開源,不忘初衷
————————————————
原文鏈接:https://blog.csdn.net/ServiceComb/article/details/87100213