1. 程式人生 > >【3分鐘就會系列】使用Ocelot+Consul搭建微服務吧!

【3分鐘就會系列】使用Ocelot+Consul搭建微服務吧!

 

【3分鐘就會系列】使用Ocelot+Consul搭建微服務吧!

 

1|0一.什麼Ocelot?

 

API閘道器是一個伺服器,是系統的唯一入口。API 閘道器一般放到微服務的最前端,並且要讓API 閘道器變成由應用所發起的每個請求的入口。這樣就可以明顯的簡化客戶端實現和微服務應用程式之間的溝通方式。從面向物件設計的角度看,它與外觀模式類似。API閘道器封裝了系統內部架構,為每個客戶端提供一個定製的API。它可能還具有其它職責,如身份驗證、監控、負載均衡、快取、請求分片與管理、靜態響應處理。

Ocelot 是一個使用在 .NET Core 平臺上的一個 API Gateway,這個專案的目標是在 .NET 上面執行微服務架構。Ocelot 框架內部集成了 IdentityServer(身份驗證)和 Consul(服務註冊發現),還引入了 Polly 來處理進行故障處理。目前,騰訊和微軟Ocelot 在官網貼出來的客戶。

2|0手把手搭建一個閘道器

 

在此之前你應該去學一學如何搭建服務叢集,那麼這將有效與你學習API閘道器服務,傳送門,再此基礎上再新增一個名為  MicroService.APIGetway 的ASP.NET WebApi專案。

在該專案中,我們通過Nuget安裝Ocelot,或者通過m命令列進行安裝。

注意:最新版的不建議使用,會出現一些內部錯誤,建議使用10.0.1以下的版本。

2|1建立相關資料夾

 

 在其中應該建立服務註冊以及閘道器資料夾,那麼效果圖如下:

2|2新增閘道器配置檔案

 

在專案中,新增一個配置檔案 ocelot.json ,並將檔案屬性中 “賦值到輸出目錄” 的值修改為 “如果較新則複製”。

 

在ocelot.json資料夾中,加入以下內容。

 

{ "ReRoutes": [ { "UseServiceDiscovery": true, "DownstreamPathTemplate": "/api/values", "DownstreamScheme": "http", "ServiceName": "T169.OcelotConsul.Service", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UpstreamPathTemplate": "/ss", "UpstreamHttpMethod": [ "Get", "Post" ], "ReRoutesCaseSensitive": false // non case sensitive } ], "GlobalConfiguration": { "ServiceDiscoveryProvider": { "Host": "localhost", // Consul Service IP "Port": 8500 // Consul Service Port } } }

以下是 Ocelot 官方給出的配置檔案的節點說明

 

{ //官⽅方⽂文件ReRoutes全節點示例例 "ReRoutes": [ { //Upstream表示上游請求,即客戶端請求到API Gateway的請求 "UpstreamPathTemplate": "/", //請求路路徑模板 "UpstreamHttpMethod": [ //請求⽅方法陣列 "Get", "POST", "PUT", "DELETE", "OPTIONS" ], //Downstreamb表示下游請求,即API Gateway轉發的⽬目標服務地址 "DownstreamScheme": "http", //請求協議,⽬目前應該是⽀支援http和https "DownstreamHostAndPorts": [ { "Host": "localhost", //請求服務地址,應該是可以是IP及域名 "Port": 8081 //端⼝口號 } ], "DownstreamPathTemplate": "/", //下游請求地址模板 // 以下節點可選 "RouteClaimsRequirement": { //標記該路路由是否需要認證 "UserType": "registered" //示例例,K/V形式,授權宣告,授權token中 會包含⼀一些claim,如填寫則會判斷是否和token中的⼀一致,不不⼀一致則不不準訪問 }, //以下三個是將access claims轉為⽤使用者的Header Claims,QueryString,該 功能只有認證後可⽤用 "AddHeadersToRequest": { // "UserType": "Claims[sub] > value[0] > |", //示例例 "UserId": "Claims[sub] > value[1] > |" //示例例 }, "AddClaimsToRequest": {}, "AddQueriesToRequest": {}, "RequestIdKey": "", //設定客戶端的請求標識key,此key在請求header中 ,會轉發到下游請求中 "FileCacheOptions": { //快取設定 "TtlSeconds": 15, //ttl秒被設定為15,這意味著快取將在15秒後過期 。 "Region": "" //快取region,可以使⽤用administrator API清除 }, "ReRouteIsCaseSensitive": false, //路路由是否匹配⼤大⼩小寫 "ServiceName": "", //服務名稱,服務發現時必填 "QoSOptions": { //斷路路器器配置,⽬目前Ocelot使⽤用的Polly "ExceptionsAllowedBeforeBreaking": 0, //開啟斷路路器器之前允許的例例 外數量量。 "DurationOfBreak": 0, //斷路路器器復位之前,開啟的時間(毫秒) "TimeoutValue": 0 //請求超時時間(毫秒) }, "LoadBalancer": "", //負載均衡 RoundRobin(輪詢)/LeastConnection( 最少連線數) "RateLimitOptions": { //官⽅方⽂文件未說明 "ClientWhitelist": [], // 客戶端⽩白明代 ? "EnableRateLimiting": false, // 是否限流 ? "Period": "", "PeriodTimespan": 0, "Limit": 0 }, "AuthenticationOptions": { //認證配置 "AuthenticationProviderKey": "", //這個key對應的是程式碼中.AddJW TBreark中的Key "AllowedScopes": [] //使⽤用範圍 }, "HttpHandlerOptions": { "AllowAutoRedirect": true, //指示請求是否應該遵循重定向響應。 如果請求應該⾃自動遵循來⾃自Downstream資源的重定向響應,則將其設定為true; 否則為假。 預設值是true。 "UseCookieContainer": true //該值指示處理理程式是否使⽤用CookieCon tainer屬性來儲存伺服器器Cookie,並在傳送請求時使⽤用這些Cookie。 預設值是true。 }, "UseServiceDiscovery": false //使⽤用服務發現,⽬目前Ocelot只⽀支援Consu l的服務發現 } ], "GlobalConfiguration": {} }

其中,我們需要了解一下微服務的上游伺服器和下游伺服器,以下是我個人的總結,下游伺服器是提供Api介面,那麼上游提供訪問的規則,下游伺服器配置就是我們剛才建立的json裡面的,我們指定Host,port,以及PathTemplate。

通過配置檔案,我們可以可以知道Ocelot是通過我們的json配置規則對映成了它自己可以識別的物件,轉發給了後臺的httpservice,從後端返回結果。

通過配置檔案可以完成對 Ocelot 的功能配置: 路由、服務聚合、服務發現、認證、鑑權、限流、熔斷、快取、 Header 頭傳遞 等。我們上面的配置說明都已經寫好了,比較重要的就是如下,下面你可以多留意。

  • DownstreamPathTemplate:下游戲
  • DownstreamScheme:下游服務http schema
  • DownstreamHostAndPorts:下游服務的地址,如果使用LoadBalancer的話這裡可以填多項
  • UpstreamPathTemplate: 上游也就是使用者輸入的請求Url模板
  • UpstreamHttpMethod: 上游請求http方法,可使用陣列

2|3修改啟動檔案

 

 

public class Program { public static void Main(string[] args) { IWebHostBuilder builder = new WebHostBuilder(); builder.ConfigureServices(s => { s.AddSingleton(builder); }); builder.UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureAppConfiguration((hostingContext, cfg) => { cfg.AddJsonFile("ocelot.json", false, true); }) .UseStartup<Startup>(); var host = builder.Build(); host.Run(); } }

這裡需要引用一下包:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

2|4載入中介軟體

 

 

// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddOcelot(Configuration); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); app.UseOcelot().Wait(); }

2|5修改專案載入配置檔案(launchsettings.json)

 

 

{ "profiles": { "WebApplication1": { "commandName": "Project", "launchBrowser": false, "launchUrl": "api/values", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "http://localhost:5000/" } } }

2|6設定啟動多個專案

 

因為我們需要啟動服務,還有閘道器,我們就需要設定啟動多個專案了。右擊專案屬性。

 

3|0講解

 

當然我們,還是要回顧以下伺服器叢集的服務發現是如何進行的。

這是一個很基本的json,如下圖,節點與專案之間的關係。

 

{ "services": [ { "ID": "OcelotConsul1_service", "name": "T169.OcelotConsul.Service", "tags": [ "urlprefix-/T169.Studeent.Service" ], "address": "localhost", "port": 8081, "checks": [ { "name": "Student Service check", "http": "http://localhost:8081/api/health", "interval": "10s", "timeout": "5s" } ] },{ "ID": "OcelotConsul2_service", "name": "T169.OcelotConsul.Service", "tags": [ "urlprefix-/T169.Studeent.Service" ], "address": "localhost", "port": 8080, "checks": [ { "name": "Student Service check", "http": "http://localhost:8080/api/health", "interval": "10s", "timeout": "5s" } ] } ] }

大家都知道我們在我們的服務中寫好了啟動埠和和ip地址,如以下定義。

 

{ "profiles": { "ConsulGoForProject": { "commandName": "Project", "applicationUrl": "http://localhost:8081", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }

那麼我們的配置檔案就是通過address和port進行尋找的,尋找到之後,如果啟動叢集,那麼就會將這些節點轉換成物件,通過httpclient向叢集進行對映,達到了一個這麼一個功能,其中的ID應該是一個唯一的。那麼name可以是相同的,可以讓閘道器進行一個發現,那麼閘道器是根據什麼進行分發的呢?

那麼我們的閘道器是如何找到我們的服務的呢?

 

其中的DownstreamPathTemplate是向下的模板路徑,DownstreamScheme是訪問的方式,有http和https,ServiceName是服務發現的路徑,在此其中,你的配置檔案中,如果和這個名字相同,那麼就會根據對應的address和port  去訪問DownStreamPathTemplate,那麼UpstreamPathTemplate是你要寫的別名,也就是說我們的臺伺服器無法達到匹配的時候,我們可以使用這個屬性(類似我們訪問www.baidu.com 第一次訪問和這個ServiceName相同的服務,第二次找第二個,當然這和Type:"RoundRobin" 這個屬性有極大的關聯,這個就叫做輪詢,這個屬性是Ocelot的精髓)。我們分別通過閘道器地址和服務的真實地址來訪問服務,看一看效果如何。

再此其中,我們使用開發模式進行啟動伺服器叢集。

 

consul agent -dev -config-dir=/tmp/consul/config

我們逐一將其中的api/values的控制器返回值改以下,這裡就不貼程式碼了,我們啟動專案,看一個細節。如下是剛啟動專案,還沒有啟動叢集的時候是這個樣子的,這是大家都經常看到的。

我們開始部署叢集,回車!,發現諸多的程式碼在執行,如下圖所示,這是我們通過consul的命令去掃描了tmp/consul/config/ 這裡面的json,當然它只認識json,讀取其中的節點,通過Consul的自動代理HttpClient註冊我們的服務,那麼這就是一個通俗易懂的解釋了。

 

我們看一下閘道器的效果如何,我們發現這是非常榜的,這也就是輪詢機制,通過閘道器代理給我們帶來了極大的好處。

 

那麼大家都知道WebApi限流機制,限流這個名詞我就不再解釋了,對請求進行限流可以防止下游伺服器因為訪問過載而崩潰,這個功能就是我們的張善友張隊進新增進去的。非常優雅的實現,我們只需要在路由下加一些簡單的配置即可以完成。

 

"RateLimitOptions": { "ClientWhitelist": [], "EnableRateLimiting": true, "Period": "1s", "PeriodTimespan": 1, "Limit": 1 }

  • ClientWihteList 白名單
  • EnableRateLimiting 是否啟用限流
  • Period 統計時間段:1s, 5m, 1h, 1d
  • PeroidTimeSpan 多少秒之後客戶端可以重試
  • Limit 在統計時間段內允許的最大請求數量

4|0總結

 

 希望大家看完這篇可以有所收穫吧,Ocelot開源地址:https://github.com/TomPallister/Ocelot,如果有問題的話在下方留言。謝謝。!