.net core Ocelot+Consul實現網關及服務注冊和服務發現


  Ocelot是一個用.NET Core實現並且開源的API網關。對於網關概念不是很清楚的可以參照https://www.jianshu.com/p/7baab672b822

       Consul 是 HashiCorp 公司的一個用於實現分布式系統的服務發現與配置工具。Consul內置了服務注冊與發現框 架、分布一致性協議實現、健康檢查、Key/Value存儲、多數據中心方案。

   這篇文章將一步一步介紹如何使用Ocelot+consul實現網關及服務注冊和服務發現功能。

 

 一、安裝Consul,安裝后的效果如下圖。

 

 

二、建立項目。

使用.net core 新建三個webAPI項目,分別為網關、服務A和服務B,建好后的項目結構如下圖

 

 三、網關配置

ApiGateway是網關項目,為其添加Ocelot和consul包,具體的依賴包如下圖。

 

 然后在ConfigureServices方法中添加Ocelot和Consul的注入,代碼如下,其中AddJsonFile("ocelot.json")指定了ocelot的配置文件。

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
    services.AddOcelot(new ConfigurationBuilder() .AddJsonFile("ocelot.json") .Build()).AddConsul();
        }

 

在Configure方法中添加ocelot中間件

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseOcelot(); if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

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

 

添加ocelot.json配置文件,在配置文件中,可以配置服務發現、路由、負載均很、鑒權、熔斷限流等。這里只演示路由和服務發現功能,如下圖。

 

 Routes配置路由信息, "UseServiceDiscovery": true,表示使用服務發現功能,

"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",

指定了下游的url及使用的通信協議,{url}是通配的意思。

 "ServiceName": "ServiceA",指定下游使用的服務名是ServiceA,使用ServiceA這個服務名到consul服務器去發現下游對應的IP及端口。

"UpstreamPathTemplate": "/ServiceA/{url}",
"UpstreamHttpMethod": [ "Get" ]

指定了上游的訪問路由格式及請求方式。

"GlobalConfiguration": {
"BaseUrl": "https://192.168.0.103:5000",
"ServiceDiscoveryProvider": {
"Host": "192.168.0.102",
"Port": 8500,
"Type": "Consul"
}
}

這段是全局配置,BaseUrl表示ocelot上游使用的IP及端口。ServiceDiscoveryProvider指定Consul的服務器和端口,用於服務發現。至此,api網關部分已經完成。

 

四、webapi配置

為ServiceA和ServiceB分別添加consul的nuget包。

 

 然后在appsettings.json中配置consul服務器的配置信息。如下圖

 這里需要注意ServiceName,在Ocelot中使用的服務發現名也就是ServiceA這個名字,也就是說,服務需要先到Consul上注冊,然后才能發現。

 

 

添加健康檢查接口

  [Route("[controller]/[action]")]
    [ApiController]
    public class HealthController : ControllerBase
    {
        [HttpGet("/healthCheck")]
        public IActionResult Check() => Ok("ok");
    }

 

接着我們添加兩個文件ConsulBuilderExtensions.cs和ConsulOption.cs用於注冊Consul.

 public static class ConsulBuilderExtensions
    {
        public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ConsulOption consulOption)
        {
            var consulClient = new ConsulClient(x =>
            {
                // consul 服務地址
                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;
        }
    }
 /// <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; }
    }

 

然后在startup.cs中使用consul中間件

   public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApplicationLifetime lifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();
            var consulOption = new ConsulOption { ServiceName = Configuration["ServiceName"], ServiceIP = Configuration["ServiceIP"], ServicePort = Convert.ToInt32(Configuration["ServicePort"]), ServiceHealthCheck = Configuration["ServiceHealthCheck"], Address = Configuration["ConsulAddress"] }; app.RegisterConsul(lifetime, consulOption);
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

 

至此大功告成,我們看一下效果。將三個項目均設置為啟動項目,並啟動。

consul服務器看到了注冊到的ServiceA和ServiceB

 

 

如下圖,訪問Ocelot上游路由地址http://192.168.0.103:5000/ServiceA/weatherforecasthttp://192.168.0.103:5000/ServiceB/weatherforecast,可以正確訪問到服務A和服務B。路由及服務注冊、服務發現均已實現。

 

 

 

源代碼地址:https://gitee.com/lp244392323/LP.Demo/tree/master/OcelotWithConsul/WebAppOcelotWithConsul


免責聲明!

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



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