第五節:基於Ocelot網關簡介、路由功能、集成Consul使用


一. 基礎說明

1. API網關剖析

(1).什么是Api

 API是Application Programming Interface縮寫,翻譯成中文就是應用程序接口。在實際微服務中可以理解一個個功能方法。就比如你一個商品服務的微服務, 可以對外提供 API 接口為,獲取商品目錄、獲取商品詳情等。

(2).什么是網關(Gateway)

 它是一個服務器,用來轉發其他服務器通信數據的, 它接收從客戶端發送來的請求時,它就像自己擁有資源的源服務器一樣對請求進行處理。

(3).什么是Api網關

 通俗的來說就是用來限制客戶端訪問服務端api一道門檻。

2. 微服務架構中為什么要用網關?

(1).在這之前,我們的技術棧中只引入了Consul,客戶端訪問Consul拿到對應的IP+Port,最終還是要訪問業務服務器的,但很多情況我們並不想讓業務服務器直接對外開放,所以這個時候就需要引入網關進行轉發了.

(2).現在的微服務還沒有加權限校驗,如果將權限校驗加個每個微服務的業務服務器上,開發量很大,這個時候引入網關,可以在網關層校驗.

(3).沒有網關,很難做限流,而且各個業務的負責人員不能獨立負責自己的服務器器。

3. 網關都有哪些作用?

 路由、負載均衡、限流、認證、授權、鏈路監控、熔斷降級、Service Fabric

4. Ocelot相關信息

(1).依賴程序集:通過Nuget安裝 【Ocelot 16.0.1】

  GitHub地址:https://github.com/ThreeMammals/Ocelot

(2).參考文檔:

  官網:https://ocelot.readthedocs.io/en/latest/

  ocelot 中文文檔:https://blog.csdn.net/sD7O95O/article/details/79623654

  資料:http://www.csharpkit.com/apigateway.html

(3).其他網關框架:

  A. Netflix Zuul +java實現

  B. Kong nginx +lua腳本實現

  C. Tyk go語言開發,收費版本

  D. Ocelot aspnetcore開發的

5. Ocelot的原理

  Ocelot是一堆的asp.net core middleware組成的一個管道。當它拿到請求之后會用一個request builder來構造一個HttpRequestMessage發到下游的真實服務器,等下游的服務返回response之后再由一個middleware將它返回的HttpResponseMessage映射到HttpResponse上。

(1).上游是什么:Ocelot自身就是上游(Upstream)

(2).下游是什么:Ocelot轉發給的(業務)服務器就是下游(Downstream)

 

二. 路由功能

架構圖:

 

 

 

1.路由的含義

  Ocelot(即上游)按照匹配規則接收客戶端發送的請求 將客戶端請求轉換成業務服務器(即下游)的地址 → 調用下游服務,返回結果  →  Ocelot再將下游服務的結果返回給客戶端.

2. 參數介紹

  - Downstream 下游服務配置

  - UpStream 上游服務配置

  - Aggregates 服務聚合配置

  - ServiceName, LoadBalancer, UseServiceDiscovery 配置服務發現

  - AuthenticationOptions 配置服務認證

  - RouteClaimsRequirement 配置Claims鑒權

  - RateLimitOptions 限流配置

  - FileCacheOptions 緩存配置

  - QosOptions 服務質量與熔斷

  - DownstreamHeaderTransform 頭信息轉發

3. 路由直接轉發指定的地址

(1).業務場景:

  客戶端訪問網關 → 網關把請求直接轉發給"指定ip+端口"業務服務器 (該場景網關本身不配置Consul,直接轉發)

(2).業務編寫與測試:

 A. 新建網關項目OcelotGateWay,通過Nuget安裝【Ocelot 16.0.1】程序集

 B. 新建一個OcelotConfig.json的配置文件,屬性改為"始終復制",用於存放Ocelot的配置。

代碼如下:

{
  "Routes": [
    {
      //轉發下游(業務服務器)的匹配規則
      "DownstreamPathTemplate": "/api/{url}",
      //下游請求類型
      "DownstreamScheme": "http",
      //下游的ip和端口,和上面的DownstreamPathTemplate匹配起來
      "DownstreamHostAndPorts": [
        {
          "Host": "127.0.0.1",
          "Port": 7001
        }
      ],
      //上游(即Ocelot)接收規則
      "UpstreamPathTemplate": "/GoodsService/{url}",
      //上游接收請求類型
      "UpstreamHttpMethod": [ "Get", "Post" ]
    },
    {
      "DownstreamPathTemplate": "/api/{url}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "127.0.0.1",
          "Port": 7004
        }
      ],
      "UpstreamPathTemplate": "/OrderService/{url}",
      "UpstreamHttpMethod": [ "Get", "Post" ]
    }
  ]
}

剖析上述xml:

- DownstreamPathTemplate:下游路徑模板

- DownstreamScheme:下游服務http schema

- DownstreamHostAndPorts:下游服務的地址,如果使用LoadBalancer的話這里可以填多項

- UpstreamPathTemplate: 上游也就是用戶輸入的請求Url模板,會將這個請求轉發給下游,如上代碼,客戶端請求 :網關ip+端口/GoodsService/{url},會轉發給下游:127.0.0.1:7001/api/{url}

- UpstreamHttpMethod: 上游請求http方法,可使用數組

 C. 在Program中通過AddJsonFile將上述json文件加載進來.

  public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                //配置相關
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    //1. 加載json文件 (配置后面兩個參數為true,當配置文件發生變化的時候,會自動更新加載,而不必重啟整個項目)
                    config.AddJsonFile("OcelotConfig.json", optional: true, reloadOnChange: true);
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    //添加命令行支持(寫在上面的Main里也可以)
                    var config = new ConfigurationBuilder().AddCommandLine(args).Build();
                    webBuilder.UseStartup<Startup>();
                });

 D. 在Startup中進行注冊和使用,services.AddOcelot(); app.UseOcelot().Wait();

   public void ConfigureServices(IServiceCollection services)
        {
            //1.注冊Ocelot
            var ocelot = services.AddOcelot();
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //1.使用Ocelot
            app.UseOcelot().Wait();    //這里不寫異步用法了

            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

 E. 啟動項目,7001端口啟動GoodsService、7004端口啟動OrderService、7020端口啟動OcelotGateWay,指令如下:

  【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001】 業務服務器地址

  【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004】   業務服務器地址

  【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020】  網關地址

 F. PostMan測試

 (1). Get測試: http://127.0.0.1:7020/GoodsService/Catalog/GetGoodById1?id=123,會將請求地址轉發給  http://127.0.0.1:7001/api/Catalog/GetGoodById1?id=123 ,請求成功。

 

 (2).  Post請求:http://127.0.0.1:7020/OrderService/Buy/pOrder1,會將請求地址轉發給  http://127.0.0.1:7004/api/Buy/pOrder1,請求成功。

 

 

三. 集成Consul

  與Consul結合實現業務服務器的負載均衡(推薦用法)

架構圖:

 

 

 

1.業務背景

  上述通過 Ocelot直接轉發給指定的 ip+端口,只是為了演示,實際場景中,比如OrderService這個業務服務器,會部署在多台服務器上進行分攤請求壓力,當然我可以利用Ocelot自身實現負載均衡,但不推薦,原因有二: ① Ocelot本身的負載均衡機制不完善 ② 每次增加或減少業務服務器,都需要改網關的配置文件,耦合性很強。

       解決方案:Ocelot與Consul結合,客戶端訪問網關→網關通過ServiceName去Consul中找一個地址進行匹配訪問(Ocelot提供了多種算法去Consul中找地址)

2.業務編寫與測試

 A. 通過Nuget安裝【Ocelot 16.0.1】程序集 和 【Ocelot.Provider.Consul 16.0.1】程序集

 B. 新建一個OcelotConfig.json的配置文件,屬性改為"始終復制",用於存放Ocelot的配置.

 配置分享:

//模式三:將Ocelot與consul結合處理,在consul中已經注冊業務服務器地址,在Ocelot端不需要再注冊了(推薦用法)
{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{url}",
      "DownstreamScheme": "http",
      "ServiceName": "GoodsService", //Consul中的服務名稱
      "LoadBalancerOptions": {
        "Type": "RoundRobin" //輪詢算法:依次調用在consul中注冊的服務器
      },
      "UseServiceDiscovery": true, //啟用服務發現(可以省略,因為會默認賦值)
      "UpstreamPathTemplate": "/GoodsService/{url}",
      "UpstreamHttpMethod": [ "Get", "Post" ]
    },
    {
      "DownstreamPathTemplate": "/api/{url}",
      "DownstreamScheme": "http",
      "ServiceName": "OrderService",
      "LoadBalancerOptions": {
        "Type": "LeastConnection" //最小連接數算法
      },
      "UseServiceDiscovery": true,
      "UpstreamPathTemplate": "/OrderService/{url}",
      "UpstreamHttpMethod": [ "Get", "Post" ]
    }
  ],
  //下面是配置Consul的地址和端口
  "GlobalConfiguration": {
    //對應Consul的ip和Port(可以省略,因為會默認賦值)
    "ServiceDiscoveryProvider": {
      "Host": "127.0.0.1",
      "Port": 8500
    }
  }
}

剖析配置:  

LoadBalancer將決定負載均衡的算法

- LeastConnection – 將請求發往最空閑的那個服務器

- RoundRobin – 輪流發送

- NoLoadBalance – 總是發往第一個請求或者是服務發現

ServiceName(對應服務名), UseServiceDiscovery 啟用注冊發現(可省略),ServiceDiscoveryProvider 配置Consul的ip和端口。

 C. 在Program中通過AddJsonFile將上述json文件加載進來. (代碼同上)

 D. 在Startup中進行注冊和使用,services.AddOcelot().AddConsul(); app.UseOcelot().Wait(); 

代碼分享:

        public void ConfigureServices(IServiceCollection services)
        {
            //1.注冊Ocelot和Consul
            services.AddOcelot().AddConsul();
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //1.使用Ocelot
            app.UseOcelot().Wait();    //這里不寫異步用法了

            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

 E. 啟動項目

  7001,7002,7003 端口啟動GoodsService、7004,7005,7006端口啟動OrderService、7020端口啟動OcelotGateWay

  【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001】 業務服務器1地址

  【dotnet GoodsService.dll --urls="http://*:7002" --ip="127.0.0.1" --port=7002】 業務服務器1地址

  【dotnet GoodsService.dll --urls="http://*:7003" --ip="127.0.0.1" --port=7003】 業務服務器1地址

  【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004】   業務服務器2地址

  【dotnet OrderService.dll --urls="http://*:7005" --ip="127.0.0.1" --port=7005】   業務服務器2地址

  【dotnet OrderService.dll --urls="http://*:70046" --ip="127.0.0.1" --port=7006】   業務服務器2地址

  【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020】  網關地址

 F. PostMan測試:

  (1).Get測試: http://127.0.0.1:7020/GoodsService/Catalog/GetGoodById1?id=123, 會按照輪詢算法依次轉發給 :http://127.0.0.1:7001/api/Catalog/GetGoodById1?id=123,http://127.0.0.1:7002/api/Catalog/GetGoodById1?id=123,http://127.0.0.1:7003/api/Catalog/GetGoodById1?id=123,請求成功。

  (2).Post請求:http://127.0.0.1:7020/OrderService/Buy/pOrder1 ,會根據最小連接數算法,轉發給7004 7005 7006連接數最小的業務服務器。

測試結果同上述路由轉發的圖

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM