1. 程式人生 > 其它 >Ocelot基於Consul服務發現

Ocelot基於Consul服務發現

 

Ocelot基於Consul服務發現

前言

上章節介紹了將WebAPI介面服務註冊到Consul中,這節介紹.NET Core平臺下Ocelot基於Consul的服務發現。

環境:Win10+VS2022 +.NET5.0 + Ocelot17.0.0.0 + Consul 1.6.1.1

服務發現

Ocelot 允許您指定服務發現提供程式,並將使用它來查詢 Ocelot 將請求轉發到的下游服務的主機和埠。目前這僅在 GlobalConfiguration 部分中受支援,這意味著相同的服務發現提供程式將用於您在路由級別指定 ServiceName 的所有路由。

Consul

需要做的第一件事是在

Ocelot 中安裝提供 Consul 支援的 NuGet 包。

 Install-Package Ocelot.Provider.Consul

 

然後將以下內容新增到您的 ConfigureServices 方法中。

s.AddOcelot()

 .AddConsul();

 

GlobalConfiguration 中需要以下內容。Provider 是必需的,如果您不指定主機和埠,則將使用 Consul 預設值。

請注意 Scheme 選項預設為 HTTP。它被新增到這個PR中。它預設為 HTTP 以不引入重大更改。

"ServiceDiscoveryProvider": {

    "Scheme": "https",

    "Host": "localhost",

    "Port": 8500,

    "Type": "Consul"

}

 

將來我們可以新增一個允許特定路由配置的功能。

為了告訴 Ocelot Route 是為其主機和埠使用服務發現提供程式,您必須新增您希望在向下遊發出請求時使用的 ServiceName 和負載均衡器。目前,Ocelot 有一個可以使用的 RoundRobin LeastConnection 演算法。如果沒有指定負載均衡器,Ocelot 將不會對請求進行負載均衡。

{

    "DownstreamPathTemplate": "/api/posts/{postId}",

    "DownstreamScheme": "https",

    "UpstreamPathTemplate": "/posts/{postId}",

    "UpstreamHttpMethod": [ "Put" ],

    "ServiceName": "product",

    "LoadBalancerOptions": {

        "Type": "LeastConnection"

},

}

 

設定完成後,Ocelot 將從服務發現提供者那裡查詢下游主機和埠,並在任何可用服務之間實現負載平衡請求。

很多人要求我實現一個功能,即 Ocelot 輪詢 Consul 以獲取最新的服務資訊,而不是每個請求。如果您想輪詢 Consul 以獲取最新服務而不是每個請求(預設行為),那麼您需要設定以下配置。

"ServiceDiscoveryProvider": {

    "Host": "localhost",

    "Port": 8500,

    "Type": "PollConsul",

    "PollingInterval": 100

}

 

輪詢間隔以毫秒為單位,告訴 Ocelot 多久呼叫一次 Consul 以更改服務配置。

請注意這裡有權衡。如果您輪詢 ConsulOcelot 可能不會根據您的輪詢間隔知道服務是否已關閉,並且您可能會遇到比您獲得每個請求的最新服務更多的錯誤。這實際上取決於您的服務有多不穩定。我懷疑這對大多數人來說很重要,輪詢可能會比每個請求呼叫 Consul(作為 Sidecar 代理)帶來微小的效能改進。如果您正在呼叫遠端 Consul 代理,那麼輪詢將是一個很好的效能改進。

您的服務需要新增到 Consul 中,如下所示(C# 風格,但希望這是有意義的)……唯一需要注意的是不要在地址欄位中新增 http https

"Service": {

       "ID": "some-id",

       "Service": "some-service-name",

       "Address": "localhost",

       "Port": 8080

   }

 

 

ACL 令牌

如果您將 ACL Consul Ocelot 一起使用,則支援新增 X-Consul-Token 標頭。為了使它起作用,您必須在下面新增附加屬性。

"ServiceDiscoveryProvider": {

    "Host": "localhost",

    "Port": 8500,

    "Token": "footoken",

    "Type": "Consul"

}

 

Ocelot 會將此令牌新增到它用來發出請求的 Consul 客戶端,然後用於每個請求。

 

專案實現

4.1 新建Ocelot閘道器專案

在上節的專案中再新建一個Ocelot閘道器專案,命名為“Yak.Ocelot.Gateway”,修改啟動埠為“5000”。

 "Yak.Ocelot.Gateway": {

      "commandName": "Project",

      "dotnetRunMessages": "true",

      "launchBrowser": true,

      "applicationUrl": "http://localhost:5000",

      "environmentVariables": {

        "ASPNETCORE_ENVIRONMENT": "Development"

      }

 

4.2 新增OcelotOcelotConsul依賴

新增依賴後,Yak.Ocelot.Gateway專案檔案下添加了下面程式碼。

 <ItemGroup>

    <PackageReference Include="Ocelot" Version="17.0.0" />

    <PackageReference Include="Ocelot.Provider.Consul" Version="17.0.0" />

  </ItemGroup>

 

4.3 把服務註冊到Consul

  1. 專案中新增Consul 註冊發現相關引數類ConsulOption

/// <summary>

    /// Consul 註冊發現相關引數

    /// </summary>

    public class ConsulOption

    {

        /// <summary>

        /// 服務名稱

        /// </summary>

        public string ServiceName { get; set; }

 

        /// <summary>

        /// 服務IP

        /// </summary>

        public string ServiceIP { get; set; }

 

        /// <summary>

        /// 服務埠

        /// </summary>

        public int ServicePort { get; set; }

 

        /// <summary>

        /// 服務健康檢查地址

        /// </summary>

        public string ServiceHealthCheck { get; set; }

 

        /// <summary>

        /// Consul 地址

        /// </summary>

        public string Address { get; set; }

    }

 

  1. 新增Consul註冊發現擴充套件類ConsulBuilderExtensions

public static class ConsulBuilderExtensions

    {

        public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption)

        {

            var consulClient = new ConsulClient(x =>

            {

                x.Address = new Uri(consulOption.Address);

            });

 

            var registration = new AgentServiceRegistration()

            {

                ID = Guid.NewGuid().ToString(),

                Name = consulOption.ServiceName,// 服務名

                Address = consulOption.ServiceIP, // 服務繫結IP

                Port = consulOption.ServicePort, // 服務繫結埠

                Check = new AgentServiceCheck()

                {

                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務啟動多久後註冊

                    Interval = TimeSpan.FromSeconds(10),//健康檢查時間間隔

                    HTTP = consulOption.ServiceHealthCheck,//健康檢查地址

                    Timeout = TimeSpan.FromSeconds(5)

                }

            };

 

            // 服務註冊

            consulClient.Agent.ServiceRegister(registration).Wait();

 

            // 應用程式終止時,服務取消註冊

            lifetime.ApplicationStopping.Register(() =>

            {

                consulClient.Agent.ServiceDeregister(registration.ID).Wait();

            });

            return app;

        }

    }

 

  1. 新增ocelot配置檔案,ocelot.json檔案。

{

  "Routes": [

    {

      "DownstreamPathTemplate": "/WeatherForecast",

      "DownstreamScheme": "http",

      "ServiceName": "service-a",

      "UseServiceDiscovery": true,

      "UpstreamPathTemplate": "/Weather",

      "UpstreamHttpMethod": [ "Get" ],

      "LoadBalancerOptions": {

        "Type": "RoundRobin"

      }

    }

  ],

  "GlobalConfiguration": {

    "BaseUrl": "http://localhost:5000"

  }

}

 

  1. 修改Startup

   public void ConfigureServices(IServiceCollection services)

        {

services.AddControllers();

services

                .AddOcelot()

                .AddConsul();

                 }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ConsulOption consulOption)

        {

            .........

app.UseEndpoints(endpoints =>

            {

                endpoints.MapGet("/", async context =>

                {

                    await context.Response.WriteAsync("我是Ocelot閘道器!");

                });

            });

            // 註冊

             app.UseOcelot().Wait();

            ...........

        }

 

4.4 啟動Consul

這裡是Win10系統,下載相應的Consul後,在資料夾下建立啟動BAT檔案用於啟動Consul,雙擊啟動。

4.5 服務發現

啟動Yak.Ocelot.Api”專案,檢視到服務已經註冊到Consul中。

 

 

 

 

 

4.6 除錯

執行閘道器專案Yak.Ocelot.Gateway”,通過訪問閘道器地址:http://localhost:5000/Weather訪問WebAPI天氣介面服務。

 

 

 

 

 

 

總結

通過Consul服務發現功能,先將介面服務註冊到Consul中,然後結合Ocelot,在不需要配置下游介面服務地址和埠情況下,直接就可以訪問介面服務了,省去了配置介面服務的麻煩。

鳴謝

https://ocelot.readthedocs.io/en/latest/features/servicediscovery.html

原始碼

https://github.com/yandaniugithub/NETCore/tree/main/Yak.Ocelot.Demo