微服務閘道器Ocelot
微服務閘道器是微服務架構中的核心元件,它是客戶端請求的門戶,它是呼叫具體服務端的橋樑.下面我們將使用開源專案Ocelot(https://github.com/geffzhang/Ocelot)搭建一款輕量級服務閘道器,不過在此之前我們將對微服務閘道器做個詳細介紹,以便大家更加清晰的瞭解什麼是微服務閘道器。
7.1什麼是微服務閘道器
微服務閘道器類似於經典設計模式的Façade模式,它將底層的複雜細節進行遮蔽,對外提供簡單而統一的呼叫方式,通常使用HTTP的RESTful API服務。此時,對於客戶端而言,可以是PC端網頁,也可以是移動裝置,客戶端通過HTTP方式呼叫微服務閘道器。
微服務閘道器也稱為服務閘道器(
我們使用服務閘道器(Service Gateway)來建立客戶端和服務端之間的聯絡。當客戶端傳送請求時,請求首先進入服務閘道器,隨後服務閘道器將服務請求路由轉發到具體的服務端。在路由的過程中,會涉及到具體的路由演算法,最簡單的做法是在服務閘道器中解析客戶端請求中的路徑或請求頭,從而路由到具體的服務端。
在微服務模式網站上也對服務閘道器進行了說明,可以通過以下地址瞭解API Gateway模式的具體資訊。
實際上,服務閘道器的路由過程我們稱之為“反向代理”。如果大家曾經使用過
在什麼樣場景下我們會考慮使用反向代理技術呢?
使靜態資源與動態資源分離
實現AJAX跨域訪問
搭建統一服務閘道器介面
下面我們將使用Ocelet 實現一個服務閘道器的重要特性之一:反向代理。
7.2 使用Ocelot 實現一個反向代理
Ocelot是一個使用.NET Core平臺上的一個API Gateway,這個專案的目標是在.NET上面執行微服務架構,它很好的和Identity Server整合,由
使用Ocelot 搭建一個反向代理,僅需要三步:
第一步,使用VisualStudio 2017 建立一個ASP.NET Core空專案FitApiGateway,通過Nuget安裝Ocelot
Install-PackageOcelot
第二步使用ASP.NET Core應用宿主Ocelot,在Startup.cs中配置,程式碼如下:
publicclassStartup
{
public Startup(IHostingEnvironment env)
{
var builder = newConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("configuration.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
// This method gets called by theruntime. Use this method to add services to the container.
// For more information on how toconfigure your application, visithttps://go.microsoft.com/fwlink/?LinkID=398940
publicvoid ConfigureServices(IServiceCollection services)
{
Action<ConfigurationBuilderCachePart> settings = (x) =>
{
x.WithMicrosoftLogging(log=>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
services.AddOcelotOutputCaching(settings);
services.AddOcelotFileConfiguration(Configuration);
services.AddOcelot();
}
publicIConfigurationRoot Configuration { get; }
// This method gets called by theruntime. Use this method to configure the HTTP request pipeline.
publicvoid Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
app.UseOcelot();
}
}
路由是Ocelot的核心配置,Ocelot的核心功能就是將到達的Http請求轉發給下游的服務,目前還只能是Http請求,將來支援其他任何傳輸機制。一條路由規則如下:
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/values",
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 9030,
"UpstreamPathTemplate": "/api/values",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"ServiceDiscoveryProvider": {
"Provider": "Consul",
"Host": "localhost",
"Port": 8500
}
}
}
DownstreamPathTemplate, DownstreamScheme,DownstreamPort 和DownstreamHost組成請求被轉發的URL,UpstreamPathTemplate是Ocelot 用於識別轉發請求,UpstreamHttpMethod用於識別相同的URL請求的不同操作。可以在模板裡使用佔位符{something},要同時出現在DownstreamPathTemplate 和UpstreamPathTemplate.。
Ocelot預設不區分大小寫,可以在配置中指定區分大小寫:
"ReRouteIsCaseSensitive": true
RequestIdKey
除了記錄訪問記錄外, 在處理每個使用者請求過程中, 涉及業務邏輯處理和後端服務呼叫等, 對某些操作也需要記錄相應日誌和錯誤.對每個請求, 都生成一個唯一的requestID. 在這個請求的生命週期中, 所有列印的日誌都會帶上requestID資訊,通過RequestI還可以構建Http請求路徑,前端一個請求,可能要經過後端好幾個服務,可以在http頭上加上RequestId和RequestIndex,把這些服務串起來,例如 A->B->C,A服務呼叫B服務的時候,如果發現http head裡面沒有RequestId,則可以通過GuId生成一個,同時RequestIndex加1 ,B服務呼叫C服務端時候, 因為RequestId已經有了,就直接傳遞下去,同時RequestIndex加1 ,把這些資訊記錄到日誌中,通過分析,整個呼叫就串起來了,通過完整的資料就可以繪製出整個服務的呼叫鏈路圖。
Ocelot從實現上來說就是一系列的中介軟體組合,在HTTP請求到達Ocelot,經過一系列的中介軟體的處理轉發到下游的服務。
至此,一個ASP.NET Core 反向代理伺服器就搭建完畢,下面我們使用Apache Bench對其效能做個簡單的測試。我們模擬了1000 個使用者,每次併發100個請求,以下是測試結果,機器的配置是CPU:Intel i5 2核, 4G記憶體的機器上測試:
D:\Workshop\ab>ab.exe -n 1000 -c 100 http://localhost:5800/api/values/
This isApacheBench, Version 2.3 <$Revision: 1757674 $>
Copyright 1996Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to TheApache Software Foundation, http://www.apache.org/
Benchmarkinglocalhost (be patient)
Completed 100requests
Completed 200requests
Completed 300requests
Completed 400requests
Completed 500requests
Completed 600requests
Completed 700requests
Completed 800requests
Completed 900requests
Completed 1000requests
Finished 1000requests
ServerSoftware: Kestrel
ServerHostname: localhost
ServerPort: 5800
DocumentPath: /api/values/
DocumentLength: 19 bytes
ConcurrencyLevel: 100
Time taken fortests: 0.230 seconds
Completerequests: 1000
Failedrequests: 0
Totaltransferred: 178000 bytes
HTMLtransferred: 19000 bytes
Requests persecond: 4345.52 [#/sec] (mean)
Time perrequest: 23.012 [ms] (mean)
Time perrequest: 0.230 [ms] (mean, acrossall concurrent requests)
Transferrate: 755.37 [Kbytes/sec]received
Connection Times(ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 4
Processing: 5 21 9.6 19 66
Waiting: 4 18 9.8 17 65
Total: 6 21 9.6 20 66
Percentage ofthe requests served within a certain time (ms)
50% 20
66% 22
75% 27
80% 30
90% 34
95% 39
98% 44
99% 48
100% 66 (longest request)
可見,平均每秒請求數(吞吐率)為4345.52, 從不同分佈下的請求數來看,響應時間也比較平穩, 相比直接訪問介面的效能相差不大。
ab.exe -n 1000 -c 100http://localhost:9030/api/values/
This is ApacheBench, Version 2.3 <$Revision:1757674 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd,http://www.zeustech.net/
Licensed to The Apache Software Foundation,http://www.apache.org/
Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: Kestrel
Server Hostname: localhost
Server Port: 9030
Document Path: /api/values/
Document Length: 19 bytes
Concurrency Level: 100
Time taken for tests: 0.200 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 158000 bytes
HTML transferred: 19000 bytes
Requests per second: 5011.40 [#/sec] (mean)
Time per request: 19.954 [ms] (mean)
Time per request: 0.200 [ms] (mean, across all concurrentrequests)
Transfer rate: 773.24 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 1
Processing: 3 19 3.4 19 29
Waiting: 2 13 4.8 13 25
Total: 3 19 3.4 20 29
Percentage of the requests served within acertain time (ms)
50% 20
66% 20
75% 21
80% 21
90% 22
95% 23
98% 25
99% 25
100% 29 (longest request)
Asp.netcore的效能絕不亞於Nginx,但擴充套件性卻遠高於Nginx,我們可以動態的指定被代理的目標地址,而在Nginx中配置的目標地址是靜態的,這一點對於我們將來實現服務發現功能及其重要,因為我們需要從ServiceRegistry中獲取需要代理的微服務資訊(例如IP和埠),並執行反向代理操作,呼叫相應的微服務REST API。
以上實際上是服務閘道器的基礎框架,將來我們會在此基礎上進行擴充套件,實現一個具有反向代理和服務發現的服務閘道器。當然服務閘道器並非僅提供反向代理與服務發現特性,此外還需要具備安全認證、效能監控、資料快取、請求分片、靜態響應等眾多特性,我們可以根據實際情況進行擴充套件。
相關文章:
.NET社群新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注