Ocelot基于Consul服务发现
Ocelot基于Consul服务发现
前言
上章节介绍了将WebAPI接口服务注册到Consul中,这节介绍.NET Core平台下Ocelot基于Consul的服务发现。
环境:Win10+VS2022 +.NET5.0 + Ocelot17.0.0.0 + Consul 1.6.1.1
1 服务发现
Ocelot 允许您指定服务发现提供程序,并将使用它来查找 Ocelot 将请求转发到的下游服务的主机和端口。目前这仅在 GlobalConfiguration 部分中受支持,这意味着相同的服务发现提供程序将用于您在路由级别指定 ServiceName 的所有路由。
2 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 以更改服务配置。
请注意这里有权衡。如果您轮询 Consul,Ocelot 可能不会根据您的轮询间隔知道服务是否已关闭,并且您可能会遇到比您获得每个请求的最新服务更多的错误。这实际上取决于您的服务有多不稳定。我怀疑这对大多数人来说很重要,轮询可能会比每个请求调用 Consul(作为 Sidecar 代理)带来微小的性能改进。如果您正在调用远程 Consul 代理,那么轮询将是一个很好的性能改进。
您的服务需要添加到 Consul 中,如下所示(C# 风格,但希望这是有意义的)……唯一需要注意的是不要在地址字段中添加 http 或 https。
"Service": { "ID": "some-id", "Service": "some-service-name", "Address": "localhost", "Port": 8080 } |
3 ACL 令牌
如果您将 ACL 与 Consul Ocelot 一起使用,则支持添加 X-Consul-Token 标头。为了使它起作用,您必须在下面添加附加属性。
"ServiceDiscoveryProvider": { "Host": "localhost", "Port": 8500, "Token": "footoken", "Type": "Consul" } |
Ocelot 会将此令牌添加到它用来发出请求的 Consul 客户端,然后用于每个请求。
4 项目实现
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 添加Ocelot和Ocelot的Consul依赖
添加依赖后,Yak.Ocelot.Gateway项目文件下添加了下面代码。
<ItemGroup> <PackageReference Include="Ocelot" Version="17.0.0" /> <PackageReference Include="Ocelot.Provider.Consul" Version="17.0.0" /> </ItemGroup> |
4.3 把服务注册到Consul
- 项目中添加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; } } |
- 添加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; } } |
- 添加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" } } |
- 修改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天气接口服务。
5 总结
通过Consul服务发现功能,先将接口服务注册到Consul中,然后结合Ocelot,在不需要配置下游接口服务地址和端口情况下,直接就可以访问接口服务了,省去了配置接口服务的麻烦。
6 鸣谢
https://ocelot.readthedocs.io/en/latest/features/servicediscovery.html
7 源码
https://github.com/yandaniugithub/NETCore/tree/main/Yak.Ocelot.Demo
本文来自博客园,作者:{春光牛牛,yak},转载请注明原文链接:https://www.cnblogs.com/yakniu/p/16109601.html
欢迎各位大佬们评论指正
QQ讨论群:610129902