前言
網關(Gateway)在微服務架構中至關重要,可以將其理解為是外部客戶端(前端、MVC后台等調用方)與后台服務的連接點,通過這層可以做統一的處理,比如路由、身份認證和授權、服務治理等;
網關的好處:
- 統一入口,調用方(客戶端)不在為調哪個服務而頭大,統一入口即可,由網關路由到對應后台服務;
- 統一處理公共邏輯,比如認證和授權,避免相同邏輯多處實現,易於維護;
- 對后台服務可以做負載均衡,根據指定的負載算法找到合適的后台服務調用,而這些細節調用方都不用理會,只管調就行啦;
- 初步過濾非法請求,可以根據配置的請求規則過濾掉非法請求;
- 屏蔽各服務真實地址,間接保證各服務的安全;
網關帶來的問題:
- 在請求過程中,多增加了一層(網關)對請求進行處理,會消耗一些性能;
- 高並發場景,對網關性能要求高,需要開發人員要有足夠的能力處理;
整體來看,在微服務架構中,網關帶來的便捷和好處肯定大於自身帶來的問題,所以不必糾結於此。
目前常用的網關有Kong、Tyk、Zuul、Ambassador、Ocelot等,而在.Net中比較火的是Ocelot和Kong,接下來就以Ocelot為主展開來聊聊。
正文
Ocelot是一個用.NET Core實現並且開源的API網關,它功能強大,除了路由、請求聚合、負載均衡等功能外,還可以集成Consul做服務發現,集成Polly做服務治理等; 相關功能只需簡單的配置即可實現。接下來就把比較常用的功能依次舉例演示一把,小伙伴們,搞起來~~~
0. 先把項目建好
整個演示中會使用到三個角色:網關層(端口為5000)、后台服務1(端口為8000)、后台服務2(端口為8001)。項目結構如下:
網關對應代碼如下:
由於使用的是.NetCore3.1進行演示,則需要的Ocelot包版本最新為16.0.1,然后將對應服務和中間件進行注冊;由於Ocelot是通過配置文件進行功能配置的,所以需要一個配置文件,並指定對應的路徑;這里的ocelot.json(名字自定義就行)就放在根目錄下,將文件屬性改為始終復制或如果較新則復制,配置文件內容在下面會細說;這里網關層就完工啦;
兩個后台服務接口基本上沒動,只是將ServiceAPI1的端口改為8000,ServiceAPI2的端口改為8001;為了后續配置演示,分別新增了控制器,如下圖:
1. 路由
路由是指網關根據原始請求,匹配對應的路由配置規則,將其轉發到真正的后台服務接口;這是網關的核心功能。
1.1 配置初體驗
通過配置,實現統一入口(網關),訪問后台兩個不同的服務接口,如下配置:
{
"Routes": [
{
"UpstreamPathTemplate": "/OcelotTest1/{url}",
"UpstreamHttpMethod": [ "Get"],
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8000
}
]
},
{
"UpstreamPathTemplate": "/OcelotTest2/{url}",
"UpstreamHttpMethod": [ "Get"],
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 8001
}
]
}
]
}
配置項解析:
- Routes:這是個數組,將所有請求處理都配置在里面,每一個請求處理是一個對象;
- UpstreamPathTemplate:上游請求路徑模板;即對應調用方發出的請求,如不符合這個規則,就會被過濾掉;
- UpstreamHttpMethod:上游請求的方式,可以傳遞多個,比如["Get","Post"];
- DownstreamPathTemplate:下游請求的路徑模板;對應真實API的請求地址,只有符合規則,才會正常轉發到服務接口上;
- DownstreamScheme:指定下游是http還是https;
- DownstreamHostAndPorts:指定下游的Host和端口,這里可以寫多個,多個時可以配置負載均衡;
將網關、后台服務接口1和后台服務接口2運行啟動,訪問如下:
如路由配置所示,可以用{參數}這種形式,通過上游請求模板傳遞給下游請求模板中;
1.2 設置匹配的優先級
當請求匹配到配置的多個路由規則時,會選擇配置在最前面的路由規則進行轉發,可能不是自己需要,如下:
遇到這種情況可以調整配置位置來滿足需求,但明顯不合理,Ocelot提供優先級(Priority)的配置,配置的值越大就越優先匹配,默認所有配置的路由優先級的值為0;如下配置可以滿足需求:
在配置文件中可以配置萬能模板,即所有請求都會匹配到該路由模板,但其優先級為最低,如果能匹配到其他模板,優先走其他路由,萬能模板配置如下:
1.3 區分匹配路由大小寫
默認情況下,匹配路由是不區分大小寫的;其實在實際過程中我們通常也不需要區分;但在一些應用場景要求區分大小,那就可以增加"RouteIsCaseSensitive": true配置即可。
2. 路由聚合
路由聚合就是可以將多個一般的路由(上面配置的路由就是)聚合在一起,然后將多個路由響應的結果統一返回給調用方;如下配置
配置說明:
- 路由配置中增加了Key,給需要聚合的路由分別配置一個不重復的Key值;
- 在配置文件中增加Aggregates節點,這個節點和Routes節點是同級的;然后在里面的RouteKeys中配置需要聚合的路由Key,然后再配置一個上游模板路徑,配置上游模板路徑時同樣可以傳遞參數,如上圖所示;
運行結果:
其實在剛開始直接返回字符串時(通常都是是返回Json,只是這里演示遇到了不規范情況,剛好可以說說),返回的結果並不是真正的Json字符串,這樣可能前端解析就會出問題,所以需要處理一下返回結果;
如果不處理,就會出現如下情況:
上圖中在沒處理之前,網關是直接將結果進行拼接,但最后整體不符合Json格式,JsonView就報錯啦!!!
解決措施就是將字符串以Json的形式返回即可,簡單的處理方式如下:
上面的聚合演示是默認情況,Ocelot提供自定義聚合器的功能(繼承IDefinedAggregator接口),並注冊相關服務,然后在配置文件指定自定義的聚合器即可,如下(具體細節請詳見官網):
具體實現這里就不再演示了,好像自定義聚合器功能用的不太多,通常大家的做法是單獨做一個后台聚合服務,若需要聚合數據,從聚合服務中獲取即可;
3. 集成Consul做服務發現
如果還是通過配置文件一個一個的配置路由,是不是也太不給力啦,如果能和Consul結合,豈不是完美~~~
3.1 先把Consul集成到網關項目中
引入Ocelot.Provider.Consul,並在ConfigureServices中注冊相關服務組件;
3.2 在配置文件中增加Consul相關配置;
配置文件說明:
-
GlobalConfiguration:全局配置,其實可以理解為所有路由共用的配置放在這;
-
ServiceDiscoveryProvider:服務發現的相關配置,Scheme代表用的是http還是https;Host代表的是Consul啟動的主機;Port代表Consul啟動的Http端口;Type這里使用的是Consul這種服務發現,可以指定其他服務發現框架;
-
BaseUrl:這個配置主要網關對外暴露的地址,也就是調用者使用的地址;
Routes中多了兩個和一般路由不同的配置,如下:
-
ServiceName:指定服務名,這里是Consul注冊服務時指定的服務名,根據這個名字內部可以獲取到對應的Host和端口;所以有了ServiceName,就可以不用手動配置Host和端口啦;
-
LoadBalancerOptions:指定負載均衡算法,其實這里咱們還沒有說到負載均衡,但如果不配置會報錯,所以就提前配置上了;
3.3 啟動Consul服務
將兩個后台服務接口注冊到Consul中;(過程就不細說啦,詳細參考來,Consul 服務發現入個門(一看就會的那種)和運維小姐姐說這篇Consul集群和ACL配置超給力(保姆級)這兩篇文章);這里用配置文件的方式,如下配置文件:
然后啟動Consul即可,這里為了演示方便,直接就用開發者模式啦;
3.4 運行結果
3.5 動態路由
除了以上顯示指定服務名之外,其實可以動態路由,如下配置運行:
Routes節點不需要配置任何路由;
4. 負載均衡
在高並發場景,后台服務是需要做集群部署的,而Ocelot可以在配置路由規則時,開啟負載均衡功能,並指定對應的均衡算法,從而實現請求按算法轉發到后台服務。
4.1 模擬集群環境
為了方便演示集群效果,這里將后台服務主機的端口打印出來,代碼如下:
然后通過命令的方式,將ServiceAPI1后台服務啟動多個,只是端口不一樣而已;如下:
4.2 將啟動起來的服務配置網關中
啟動起來之后,將他們配置到路由中,如下:
配置解析:
- DownstreamHostAndPorts中配置多個啟動的后台服務Host和端口;
- LoadBalancerOptions指定負載均衡算法,圖中指定的是輪詢,通常有以下幾種:
- LeastConnection 把新請求轉發到請求最少的后台服務上;
- RoundRobin 將請求輪詢輪詢轉發都配置的后台服務上;
- NoLoadBalancer 不負載均衡;
- CookieStickySessions 使用cookie關聯相關的請求到指定的服務;
4.3 網關運行起來看效果
4.4 搭配Consul一塊用
首先進行修改Consul的配置文件,然后將其啟動,見下圖:
如上圖所示,在相同服務名ServiceAPI1Name下面注冊了兩個服務,一個端口是8000,一個端口是8003;
然后在網關中修改一下配置,然后啟動:
咦,到這發現篇幅略長啦,先暫停吧;另外Polly這個知識點之前沒聊過,下期先補上,然后繼續聊其他功能~~~
總結
本來想通過一篇文章把常用的功能點演示一下的,篇幅太長不太好(小伙伴有反應);下期會繼續說Ocelot集成CacheManager做緩存、集成IdentityServer4做認證授權、集成Polly做服務治理。
一個被程序搞丑的帥小伙,關注"Code綜藝圈",跟我一起學~~~