2025年3月29日 星期六 甲辰(龙)年 月廿八 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > .net

.NET Core Consul服务发现

时间:12-15来源:作者:点击数:23

.NET Core Consul服务注册一文中讲述了安装Consul,注册服务。

本文讲述在.NET Core项目中的Consul服务发现。和注册一样,为了复用还是新建一个类库。

.NET Core Consul服务发现

首先我们还是启动3个AspNetCore服务,注册到Consul,如何注册可以看.NET Core Consul服务注册一文中的介绍。

启动好以后在Consul的监视界面localhost:8500中可以看到3个服务了,如图所示

.NET Core Consul服务发现

接下来开始在ConsulServiceDiscovery类库项目中编写代码。

服务提供IServiceProvider接口和ConsulServiceProvider类代码

  • namespace ConsulServiceDiscovery
  • {
  • public interface IServiceProvider
  • {
  • Task<IList<string>> GetServicesAsync(string serviceName);
  • }
  • }
  • namespace ConsulServiceDiscovery
  • {
  • public class ConsulServiceProvider : IServiceProvider
  • {
  • private readonly ConsulClient _consulClient;
  • public ConsulServiceProvider(Uri uri) {
  • _consulClient = new ConsulClient(consulConfig =>
  • {
  • consulConfig.Address = uri;
  • });
  • }
  • public async Task<IList<string>> GetServicesAsync(string serviceName)
  • {
  • // Health 当前consul里已注册的服务,健康检查的信息也拿过来
  • var queryResult = await _consulClient.Health.Service(serviceName, string.Empty, true);
  • var result = new List<string>();
  • foreach (var item in queryResult.Response) {
  • result.Add($"{item.Service.Address}:{item.Service.Port}");
  • }
  • return result;
  • }
  • }
  • }

服务创建IServiceBuilder接口和ServiceBuilder类代码

  • namespace ConsulServiceDiscovery.Builder
  • {
  • public interface IServiceBuilder
  • {
  • /// <summary>
  • /// 服务提供者
  • /// </summary>
  • IServiceProvider ServiceProvider { get; set; }
  • /// <summary>
  • /// 服务名称
  • /// </summary>
  • string ServiceName { get; set; }
  • /// <summary>
  • /// Uri方案
  • /// </summary>
  • string UriScheme { get; set; }
  • /// <summary>
  • /// 使用哪种策略
  • /// </summary>
  • ILoadBalancer LoadBalancer { get; set; }
  • Task<Uri> BuildAsync(string path);
  • }
  • }
  • namespace ConsulServiceDiscovery.Builder
  • {
  • public class ServiceBuilder : IServiceBuilder
  • {
  • public IServiceProvider ServiceProvider { get; set; }
  • public string ServiceName { get; set; }
  • public string UriScheme { get; set; }
  • public ILoadBalancer LoadBalancer { get; set; }
  • public ServiceBuilder(IServiceProvider serviceProvider) {
  • ServiceProvider = serviceProvider;
  • }
  • public async Task<Uri> BuildAsync(string path)
  • {
  • var serviceList = await ServiceProvider.GetServicesAsync(ServiceName);
  • var service = LoadBalancer.Resolve(serviceList);
  • var baseUri = new Uri($"{UriScheme}://{service}");
  • var uri = new Uri(baseUri, path);
  • return uri;
  • }
  • }
  • }

负载方式,这里列举随机和轮询两种负载方式,ILoadBalancer接口,RandomLoadBalancer实现类,RoundRobinLoadBalancer实现类,TypeLoadBalancer静态类代码

  • namespace ConsulServiceDiscovery.LoadBalancer
  • {
  • public interface ILoadBalancer
  • {
  • string Resolve(IList<string> services);
  • }
  • }
  • namespace ConsulServiceDiscovery.LoadBalancer
  • {
  • public class RandomLoadBalancer : ILoadBalancer
  • {
  • private readonly Random _random = new Random();
  • public string Resolve(IList<string> services)
  • {
  • var index = _random.Next(services.Count);
  • return services[index];
  • }
  • }
  • }
  • namespace ConsulServiceDiscovery.LoadBalancer
  • {
  • public class RoundRobinLoadBalancer : ILoadBalancer
  • {
  • private readonly object _lock = new object();
  • private int _index = 0;
  • public string Resolve(IList<string> services)
  • {
  • lock (_lock) {
  • if (_index >= services.Count) {
  • _index = 0;
  • }
  • return services[_index++];
  • }
  • }
  • }
  • }
  • namespace ConsulServiceDiscovery.LoadBalancer
  • {
  • public static class TypeLoadBalancer
  • {
  • // 单例
  • public static ILoadBalancer RandomLoad = new RandomLoadBalancer();
  • public static ILoadBalancer RoundRobinLoad = new RoundRobinLoadBalancer();
  • }
  • }

扩展方法创建ServiceBuilder

  • namespace ConsulServiceDiscovery
  • {
  • public static class ServiceProviderExtension
  • {
  • public static IServiceBuilder CreateServiceBuilder(this IServiceProvider serviceProvider, Action<IServiceBuilder> config) {
  • var builder = new ServiceBuilder(serviceProvider);
  • config(builder);
  • return builder;
  • }
  • }
  • }

这样,服务发现的代码就完成了。

下面是调用测试代码,创建一个控制台项目,在Program.cs里使用轮询的方式代码如下

  • namespace ConsulTest
  • {
  • class Program
  • {
  • static void Main(string[] args)
  • {
  • var serviceProvider = new ConsulServiceProvider(new Uri("http://localhost:8500"));
  • var aspNetCoreService = serviceProvider.CreateServiceBuilder(builder => {
  • builder.ServiceName = "AspNetCore";
  • builder.LoadBalancer = TypeLoadBalancer.RoundRobinLoad;//可选RandomLoad
  • builder.UriScheme = Uri.UriSchemeHttp;
  • });
  • var httpClient = new HttpClient();
  • for (int i = 0; i < 100; i++) {
  • Console.WriteLine($"----------第{i}次请求-----------");
  • try
  • {
  • var uri = aspNetCoreService.BuildAsync("/Health").Result;
  • Console.WriteLine($"{DateTime.Now} - 正在调用:{uri}");
  • var content = httpClient.GetStringAsync(uri).Result;
  • Console.WriteLine($"返回结果:{content}");
  • }
  • catch (Exception ex) {
  • Console.WriteLine(ex.ToString());
  • }
  • Task.Delay(500).Wait();
  • }
  • Console.ReadLine();
  • }
  • }
  • }

执行效果

.NET Core Consul服务发现

可以看到,轮询方式会轮流请求1234,1235,1236端口的三个服务地址。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门