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

一.什麼Ocelot?

API網關是一個服務器,是系統的惟一入口。API 網關通常放到微服務的最前端,而且要讓API 網關變成由應用所發起的每一個請求的入口。這樣就能夠明顯的簡化客戶端實現和微服務應用程序之間的溝通方式。從面向對象設計的角度看,它與外觀模式相似。API網關封裝了系統內部架構,爲每一個客戶端提供一個定製的API。它可能還具備其它職責,如身份驗證、監控、負載均衡、緩存、請求分片與管理、靜態響應處理。html

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

手把手搭建一個網關

在此以前你應該去學一學如何搭建服務集羣,那麼這將有效與你學習API網關服務,傳送門,再此基礎上再添加一個名爲  MicroService.APIGetway 的ASP.NET WebApi項目。git

在該項目中,咱們經過Nuget安裝Ocelot,或者經過m命令行進行安裝。github

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

建立相關文件夾

 在其中應該建立服務註冊以及網關文件夾,那麼效果圖以下:後端

添加網關配置文件

在項目中,添加一個配置文件 ocelot.json ,並將文件屬性中 「賦值到輸出目錄」 的值修改成 「若是較新則複製」。api

 

在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方法,可以使用數組

修改啓動文件

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;

加載中間件

// 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(); }

修改項目加載配置文件(launchsettings.json)

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

設置啓動多個項目

由於咱們須要啓動服務,還有網關,咱們就須要設置啓動多個項目了。右擊項目屬性。

 

講解

固然咱們,仍是要回顧如下服務器集羣的服務發現是如何進行的。

這是一個很基本的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 在統計時間段內容許的最大請求數量

總結

 但願你們看完這篇能夠有所收穫吧,Ocelot開源地址:https://github.com/TomPallister/Ocelot,若是有問題的話在下方留言。謝謝。!

相關文章
相關標籤/搜索