Asp.Net Core怎么使用Ocelot实现服务注册和发现
本文小编为大家详细介绍"Asp.Net Core怎么使用Ocelot实现服务注册和发现",内容详细,步骤清晰,细节处理妥当,希望这篇"Asp.Net Core怎么使用Ocelot实现服务注册和发现"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
1.服务注册与发现(Service Discovery)
服务注册:我们通过在每个服务实例写入注册代码,实例在启动的时候会先去注册中心(例如Consul、ZooKeeper、etcd、Eureka)注册一下,那么客户端通过注册中心可以知道每个服务实例的地址,端口号,健康状态等等信息,也可以通过注册中心删除服务实例。这里注册中心相当于是负责维护服务实例的管控中心。
服务发现:服务实例在注册中心注册之后,客户端通过注册中心可以了解这些服务实例运行状况。
2.Consul
如果要实现服务注册与发现,需要一个注册中心,这里主要介绍是Consul。
Consul官网:https://www.consul.io/,它主要功能有:服务注册与发现、健康检查、Key/Value、多数据中心。
如果在Windows上部署Consul,在consul.exe目录下执行consul.exe agent -dev
命令行即可。
3.Asp.Net Core向Consul注册服务实例
Asp.Net Core向Consul注册服务实例调用过程如下图所示:
Asp.Net Core向Consul注册服务实例需要在Gateway项目中引用Consul支持的NuGet软件包,安装命令如下:
Install-Package Ocelot.Provider.Consul
然后将以下内容添加到您的ConfigureServices方法中:
services.AddOcelot().AddConsul();
在Ocelot服务发现项目示例中,通过APIGateway项目GlobalConfiguration选项可以配置服务注册与发现,文件配置具体代码如下:
{ "Routes": [ { "UseServiceDiscovery": true, "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "ServiceName": "MyService", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UpstreamPathTemplate": "/{url}", "UpstreamHttpMethod": [ "Get" ], "ReRoutesCaseSensitive": false } ], "GlobalConfiguration": { //服务发现配置 "ServiceDiscoveryProvider": { //注册中心Consul地址 "Host": "192.168.113.128", //注册中心Consul端口号 "Port": 8500, "Type": "Consul", //以毫秒为单位,告诉Ocelot多久调用一次Consul来更改服务配置。 "PollingInterval": 100, //如果你有在Consul上配置key/value,则在这里输入配置key。 "ConfigurationKey": "MyService_AB" } }}
ServiceDiscoveryProvider选项说明:
Host:注册中心Consul地址。
Port:注册中心Consul端口号。
Type:注册中心类型。
PollingInterval:以毫秒为单位,告诉Ocelot多久调用一次Consul来更改服务配置。
ConfigurationKey:如果你有在Consul上配置key/value,则在这里输入配置key。
4.项目演示
4.1APIGateway项目
ConfigureServices添加Ocelot、Consul注入:
services.AddOcelot().AddConsul();
Configure添加使用Ocelot:
app.UseOcelot().Wait();
服务发现配置如Ocelot服务发现项目示例一样。
4.2Common项目
先安装Consul的NuGet软件包,安装命令如下:
Install-Package Consul
在该项目添加一个AppExtensions扩展类,用来对服务APIServiceA、APIServiceB项目在Consul注册实例,为了展示效果,具体代码稍作修改如下:
public static class AppExtensions{ public static IServiceCollection AddConsulConfig(this IServiceCollection services, IConfiguration configuration) { services.AddSingleton(p => new ConsulClient(consulConfig => { var address = configuration.GetValue ("Consul:Host"); consulConfig.Address = new Uri(address); })); return services; } public static IApplicationBuilder UseConsul(this IApplicationBuilder app, string host = null, string port = null) { //获取consul客户端实例 var consulClient = app.ApplicationServices.GetRequiredService (); var logger = app.ApplicationServices.GetRequiredService ().CreateLogger("AppExtensions"); var lifetime = app.ApplicationServices.GetRequiredService (); if (!(app.Properties["server.Features"] is FeatureCollection features)) return app; //var addresses = features.Get (); //var address = addresses.Addresses.FirstOrDefault(); //if (address == null) //{ // return app; //} var address = host + ":" + port; if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(port)) { Console.WriteLine($"host或者port为空!"); return app; } Console.WriteLine($"address={address}"); var uri = new Uri(address); Console.WriteLine($"host={uri.Host},port={uri.Port}"); var registration = new AgentServiceRegistration() { ID = $"MyService-{uri.Port}", Name = "MyService", Address = $"{uri.Host}", Port = uri.Port, Check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔 HTTP = $"{address}/HealthCheck",//健康检查地址 Timeout = TimeSpan.FromSeconds(5)//超时时间 } }; logger.LogInformation("Registering with Consul"); logger.LogInformation($"Consul RegistrationID:{registration.ID}"); //注销 consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true); //注册 consulClient.Agent.ServiceRegister(registration).ConfigureAwait(true); //应用程序关闭时候 lifetime.ApplicationStopping.Register(() => { //正在注销 logger.LogInformation("Unregistering from Consul"); consulClient.Agent.ServiceDeregister(registration.ID).ConfigureAwait(true); }); //每个服务都需要提供一个用于健康检查的接口,该接口不具备业务功能。服务注册时把这个接口的地址也告诉注册中心,注册中心会定时调用这个接口来检测服务是否正常,如果不正常,则将它移除,这样就保证了服务的可用性。 app.Map("/HealthCheck", s => { s.Run(async context => { await context.Response.WriteAsync("ok"); }); }); return app; }}
4.3APIServiceA项目
项目添加一个Get方法,对应APIGateway项目的路由上下游配置,具体代码如下:
[Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase{ // GET api/values [HttpGet] public ActionResult> Get() { var port = Request.Host.Port; return new string[] { "value1", "value2", port.Value.ToString() }; }}
appsettings.json配置加入Consul地址:
"Consul": { "Host": "http://192.168.113.128:8500"}
4.4APIServiceB项目
项目添加一个Get方法,对应APIGateway项目的路由上下游配置,具体代码如下:
[Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase{ // GET api/values [HttpGet] public ActionResult> Get() { var port = Request.Host.Port; return new string[] { "value3", "value4", port.Value.ToString() }; }}
appsettings.json配置加入Consul地址:
"Consul": { "Host": "http://192.168.113.128:8500"}
4.5项目运行
在APIServiceA、APIServiceB项目的ConfigureServices添加Consul配置:
services.AddConsulConfig(Configuration);
在Configure添加Consul服务注册:
APIServiceA:app.UseConsul("http://172.168.18.73", "9999");APIServiceB:app.UseConsul("http://172.168.18.73", "9998");
把APIGateway、APIServiceA、APIServiceB三个项目部署到IIS上:
三个项目运行起来后,通过浏览器Consul客户端可以看到MyService节点服务情况:
点击打开MyService节点可以看到注册到Consul的APIServiceA、APIServiceB服务状况:
如果把APIServiceB服务实例站点停掉:
通过Consul客户端会看到APIServiceB服务实例已经被剔除了:
如果输入CTRL+C把集群中某一个Consul服务关闭,那么集群会重新选举一个新的leader,负责处理所有服务实例的查询和事务:
读到这里,这篇"Asp.Net Core怎么使用Ocelot实现服务注册和发现"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。