(更新时间)2021年5月28日 商城高并发秒杀系统(.NET Core版) 06-注册中心组件的封装

举报
愚公搬代码 发表于 2021/10/19 00:35:03 2021/10/19
【摘要】 一:consul注册发现封装 /// <summary> /// consul服务发现实现 /// </summary> public class ConsulServiceDi...

一:consul注册发现封装

/// <summary>
/// consul服务发现实现
/// </summary>
public class ConsulServiceDiscovery : AbstractServiceDiscovery
{
    public ConsulServiceDiscovery(IOptions<ServiceDiscoveryOptions> options) : base(options)
    {
    }

    /*public ConsulServiceDiscovery(IOptions<ServiceDiscoveryOptions> options)
{
this.serviceDiscoveryOptions = options.Value;
}*/

    /*public List<ServiceNode> Discovery(string serviceName)
    {
        // 1.2、从远程服务器取
        CatalogService[] queryResult = RemoteDiscovery(serviceName);

        var list = new List<ServiceNode>();
        foreach (var service in queryResult)
        {
            list.Add(new ServiceNode { Url = service.ServiceAddress + ":" + service.ServicePort });
        }

        return list;
    }*/

    protected override CatalogService[] RemoteDiscovery(string serviceName)
    {
        // 1、创建consul客户端连接 2s 1、使用单例全局共享 2、使用数据缓存(进程:字典,集合) 3、使用连接池
        var consulClient = new ConsulClient(configuration =>
        {
            //1.1 建立客户端和服务端连接
            configuration.Address = new Uri(serviceDiscoveryOptions.DiscoveryAddress);
        });

        // 2、consul查询服务,根据具体的服务名称查询
        var queryResult = consulClient.Catalog.Service(serviceName).Result;
        // 3、判断请求是否失败
        if (!queryResult.StatusCode.Equals(HttpStatusCode.OK))
        {
            throw new FrameException($"consul连接失败:{queryResult.StatusCode}");
        }

        return queryResult.Response;
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
/// <summary>
/// consul服务注册实现
/// </summary>
public class ConsulServiceRegistry : IServiceRegistry
{
    // 服务注册选项
    public readonly ServiceRegistryOptions serviceRegistryOptions;

    public ConsulServiceRegistry(IOptions<ServiceRegistryOptions> options)
    {
        this.serviceRegistryOptions = options.Value;
    }

    /// <summary>
    /// 注册服务
    /// </summary>
    public void Register()
    {
        // 1、创建consul客户端连接
        var consulClient = new ConsulClient(configuration =>
        {
            //1.1 建立客户端和服务端连接
            configuration.Address = new Uri(serviceRegistryOptions.RegistryAddress);
        });

        // 2、获取
        var uri = new Uri(serviceRegistryOptions.ServiceAddress);

        // 3、创建consul服务注册对象
        var registration = new AgentServiceRegistration()
        {
            ID = string.IsNullOrEmpty(serviceRegistryOptions.ServiceId) ? Guid.NewGuid().ToString() : serviceRegistryOptions.ServiceId,
            Name = serviceRegistryOptions.ServiceName,
            Address = uri.Host,
            Port = uri.Port,
            Tags = serviceRegistryOptions.ServiceTags,
            Check = new AgentServiceCheck
            {
                // 3.1、consul健康检查超时间
                Timeout = TimeSpan.FromSeconds(10),
                // 3.2、服务停止5秒后注销服务
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                // 3.3、consul健康检查地址
                HTTP = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceRegistryOptions.HealthCheckAddress}",
                // 3.4 consul健康检查间隔时间
                Interval = TimeSpan.FromSeconds(10),
            }
        };

        // 4、注册服务
        consulClient.Agent.ServiceRegister(registration).Wait();

        Console.WriteLine($"服务注册成功:{serviceRegistryOptions.ServiceAddress}");
        // 5、关闭连接
        consulClient.Dispose();
    }

    /// <summary>
    /// 注销服务
    /// </summary>
    /// <param name="serviceNode"></param>
    public void Deregister()
    {
        // 1、创建consul客户端连接
        var consulClient = new ConsulClient(configuration =>
        {
            //1.1 建立客户端和服务端连接
            configuration.Address = new Uri(serviceRegistryOptions.RegistryAddress);
        });

        // 2、注销服务
        consulClient.Agent.ServiceDeregister(serviceRegistryOptions.ServiceId).Wait();


        Console.WriteLine($"服务注销成功:{serviceRegistryOptions.ServiceAddress}");

        // 3、关闭连接
        consulClient.Dispose();
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

二:配置选项

/// <summary>
/// 服务发现选项
/// </summary>
public class ServiceDiscoveryOptions
{
    public ServiceDiscoveryOptions()
    {
        // 默认地址
        this.DiscoveryAddress = "http://localhost:8500";
    }

    /// <summary>
    /// 服务发现地址
    /// </summary>
    public string DiscoveryAddress { set; get; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
/// <summary>
/// 节点注册选项
/// </summary>
public class ServiceRegistryOptions
{
    public ServiceRegistryOptions()
    {
        this.ServiceId = Guid.NewGuid().ToString();
        this.RegistryAddress = "http://localhost:8500";
        this.HealthCheckAddress = "/HealthCheck";
    }

    // 服务ID
    public string ServiceId { get; set; }

    // 服务名称
    public string ServiceName { get; set; }

    // 服务地址http://localhost:5001
    public string ServiceAddress { get; set; }

    // 服务标签(版本)
    public string[] ServiceTags { set; get; }

    /*// 服务地址(可以选填 === 默认加载启动路径(localhost))
    public string ServiceAddress { set; get; }

    // 服务端口号(可以选填 === 默认加载启动路径端口)
    public int ServicePort { set; get; }

    // Https 或者 http
    public string ServiceScheme { get; set; }*/

    // 服务注册地址
    public string RegistryAddress { get; set; }

    // 服务健康检查地址
    public string HealthCheckAddress { get; set; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

三:consul相关扩展

/// <summary>
///  服务发现IOC容器扩展
/// </summary>
public static class ServiceDiscoveryServiceCollectionExtensions
{
    // consul服务发现
    public static IServiceCollection AddServiceDiscovery(this IServiceCollection services)
    {
        // 1、注册consul服务发现
        AddServiceDiscovery(services, options => { });
        return services;
    }

    public static IServiceCollection AddServiceDiscovery(this IServiceCollection services,
                                                  Action<ServiceDiscoveryOptions> options)
    {
        // 2、注册到IOC容器
        services.Configure<ServiceDiscoveryOptions>(options);

        // 3、注册consul服务发现
        services.AddSingleton<IServiceDiscovery, ConsulServiceDiscovery>();
        return services;
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
/// <summary>
/// 微服务注册扩展
/// </summary>
public static class ServiceRegistryApplicationBuilderExtensions
{
    public static IApplicationBuilder UseRegistry(this IApplicationBuilder app)
    {
        // 1、从IOC容器中获取Consul服务注册配置
        var serviceNode = app.ApplicationServices.GetRequiredService<IOptions<ServiceRegistryConfig>>().Value;

        // 2、获取应用程序生命周期
        var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

        // 2.1 获取服务注册实例
        var serviceRegistry = app.ApplicationServices.GetRequiredService<IServiceRegistry>();

        // 3、获取服务地址
        var features = app.Properties["server.Features"] as FeatureCollection;
        var address = features.Get<IServerAddressesFeature>().Addresses.First();
        var uri = new Uri(address);

        // 4、注册服务
        serviceNode.Id = Guid.NewGuid().ToString();
        //serviceNode.Address = $"{uri.Scheme}://{uri.Host}";
        serviceNode.Address = uri.Host;
        serviceNode.Port = uri.Port;
        serviceNode.HealthCheckAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceNode.HealthCheckAddress}";
        serviceRegistry.Register(serviceNode);

        // 5、服务器关闭时注销服务
        lifetime.ApplicationStopping.Register(() =>
        {
            serviceRegistry.Deregister(serviceNode);
        });

        return app;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
/// <summary>
///  服务注册IOC容器扩展
/// </summary>
public static class ServiceRegistryServiceCollectionExtensions
{
    // consul服务注册
    public static IServiceCollection AddServiceRegistry(this IServiceCollection services)
    {
        AddServiceRegistry(services, optons => { });
        return services;
    }

    // consul服务注册
    public static IServiceCollection AddServiceRegistry(this IServiceCollection services, Action<ServiceRegistryOptions> options)
    {
        // 1、配置选项到IOC
        services.Configure<ServiceRegistryOptions>(options);

        // 2、注册consul注册
        services.AddSingleton<IServiceRegistry, ConsulServiceRegistry>();

        // 3、注册开机自动注册服务
        services.AddHostedService<ServiceRegistryIHostedService>();
        return services;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

四:相关依赖的类文件

/// <summary>
/// 服务url
/// </summary>
public class ServiceUrl
{
    public string Url { set; get; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
/// <summary>
/// 服务启动时自动注册
/// </summary>
public class ServiceRegistryIHostedService : IHostedService
{
    private readonly IServiceRegistry serviceRegistry;

    public ServiceRegistryIHostedService(IServiceRegistry serviceRegistry)
    {
        this.serviceRegistry = serviceRegistry;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        /* // 1、从IOC容器中获取Consul服务注册配置
         var serviceNode = app.ApplicationServices.GetRequiredService<IOptions<ServiceRegistryConfig>>().Value;

         // 2、获取应用程序生命周期
         var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

         // 2.1 获取服务注册实例
         var serviceRegistry = app.ApplicationServices.GetRequiredService<IServiceRegistry>();*/

        // 3、获取服务地址
        /*var features = app.Properties["server.Features"] as FeatureCollection;
        var address = features.Get<IServerAddressesFeature>().Addresses.First();*/
        //var uri = new Uri(address);

        // 4、注册服务
        /* serviceNode.Id = Guid.NewGuid().ToString();
         //serviceNode.Address = $"{uri.Scheme}://{uri.Host}";
         serviceNode.Address = uri.Host;
         serviceNode.Port = uri.Port;
         serviceNode.HealthCheckAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceNode.HealthCheckAddress}";*/

        return Task.Run(() => serviceRegistry.Register());

        /*// 5、服务器关闭时注销服务
        lifetime.ApplicationStopping.Register(() =>
        {
            serviceRegistry.Deregister(serviceNode);
        });*/
    }

    /// <summary>
    /// 服务停止时注销
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public Task StopAsync(CancellationToken cancellationToken)
    {
        serviceRegistry.Deregister();
        return Task.CompletedTask;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
/// <summary>
/// 服务注册节点
/// </summary>
public class ServiceRegistryConfig
{
    public ServiceRegistryConfig()
    {
        this.Id = Guid.NewGuid().ToString();
        this.Name = "";
        this.Address =
        this.RegistryAddress = "http://localhost:8500";
        this.HealthCheckAddress = "";
    }

    // 服务ID
    public string Id { get; set; }

    // 服务名称
    public string Name { get; set; }

    // 服务标签(版本)
    public string[] Tags { set; get; }

    // 服务地址(可以选填 === 默认加载启动路径(localhost))
    public string Address { set; get; }

    // 服务端口号(可以选填 === 默认加载启动路径端口)
    public int Port { set; get; }

    // 服务注册地址
    public string RegistryAddress { get; set; }

    // 服务健康检查地址
    public string HealthCheckAddress { get; set; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
/// <summary>
/// 服务Node,将所有服务抽象为Node
/// </summary>
public class ServiceNode
{
    public string Url { set; get; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
/// <summary>
/// 服务发现配置
/// </summary>
public class ServiceDiscoveryConfig
{
    /// <summary>
    /// 服务注册地址
    /// </summary>
    public string RegistryAddress { set; get; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
/// <summary>
/// 服务注册
/// </summary>
public interface IServiceRegistry
{
    /// <summary>
    /// 注册服务
    /// </summary>
    void Register();

    /// <summary>
    /// 撤销服务
    /// </summary>
    void Deregister();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
/// <summary>
/// 服务发现
/// </summary>
public interface IServiceDiscovery
{
    /// <summary>
    /// 服务发现
    /// </summary>
    /// <param name="serviceName">服务名称</param>
    /// <returns></returns>
    List<ServiceNode> Discovery(string serviceName);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
/// <summary>
/// 抽象服务发现,主要是缓存功能
/// </summary>
public abstract class AbstractServiceDiscovery : IServiceDiscovery
{
    // 字典缓存
    private readonly Dictionary<string, List<ServiceNode>> CacheConsulResult = new Dictionary<string, List<ServiceNode>>();
    protected readonly ServiceDiscoveryOptions serviceDiscoveryOptions;
    public AbstractServiceDiscovery(IOptions<ServiceDiscoveryOptions> options)
    {
        this.serviceDiscoveryOptions = options.Value;

        // 1、创建consul客户端连接
        var consulClient = new ConsulClient(configuration =>
        {
            //1.1 建立客户端和服务端连接
            configuration.Address = new Uri(serviceDiscoveryOptions.DiscoveryAddress);
        });

        // 2、consul 先查询服务
        var queryResult = consulClient.Catalog.Services().Result;
        if (!queryResult.StatusCode.Equals(HttpStatusCode.OK))
        {
            throw new FrameException($"consul连接失败:{queryResult.StatusCode}");
        }

        // 3、获取服务下的所有实例
        foreach (var item in queryResult.Response)
        {
            QueryResult<CatalogService[]> result = consulClient.Catalog.Service(item.Key).Result;
            if (!queryResult.StatusCode.Equals(HttpStatusCode.OK))
            {
                throw new FrameException($"consul连接失败:{queryResult.StatusCode}");
            }
            var list = new List<ServiceNode>();
            foreach (var service in result.Response)
            {
                list.Add(new ServiceNode { Url = service.ServiceAddress + ":" + service.ServicePort });
            }
            CacheConsulResult.Add(item.Key, list);
        }
    }


    public List<ServiceNode> Discovery(string serviceName)
    {
        // 1、从缓存中查询consulj结果
        if (CacheConsulResult.ContainsKey(serviceName))
        {
            return CacheConsulResult[serviceName];
        }
        else
        {
            // 1.2、从远程服务器取
            CatalogService[] queryResult = RemoteDiscovery(serviceName);

            var list = new List<ServiceNode>();
            foreach (var service in queryResult)
            {
                list.Add(new ServiceNode { Url = service.ServiceAddress + ":" + service.ServicePort });
            }

            // 1.3 将结果添加到缓存
            CacheConsulResult.Add(serviceName, list);

            return list;
        }
    }

    /// <summary>
    /// 远程服务发现
    /// </summary>
    /// <param name="serviceName"></param>
    /// <returns></returns>
    protected abstract CatalogService[] RemoteDiscovery(string serviceName);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

文章来源: codeboy.blog.csdn.net,作者:愚公搬代码,版权归原作者所有,如需转载,请联系作者。

原文链接:codeboy.blog.csdn.net/article/details/117376082

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。