.net consul 封装 演变(二)

 

上一篇重复造轮子 这一篇 进行封装

 ConfigOptions 文件夹 中的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsulCustomExtend.ConfigOptions
{
    public class ConsulSettings
    {
        public ConsulUI ConsulUI { get; set; }        
        public ConsulSevice ConsulSevice { get; set; }
    }
}

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsulCustomExtend.ConfigOptions
{
    /// <summary>
    /// 注册服务
    /// </summary>
    public class ConsulSevice
    {
        /// <summary>
        /// 服务id
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// 服务地址
        /// </summary>
        public string Address { get; set; }
        /// <summary>
        /// 服务名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 标签
        /// </summary>
        public string[] Tags { get; set; }
        /// <summary>
        /// 端口号
        /// </summary>
        public int Port { get; set; }

        public ConsulHealthCheck HealthCheck { get; set; }
    }
    /// <summary>
    /// 健康检查
    /// </summary>
    public class ConsulHealthCheck
    {
        /// <summary>
        /// 健康检查地址
        /// </summary>
        public string HTTP { get; set; }
        /// <summary>
        /// 每隔几秒 进行健康检查
        /// </summary>
        public int Interval { get; set; }
    }
}

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsulCustomExtend.ConfigOptions
{
    /// <summary>
    /// ConsulUI
    /// </summary>
    public class ConsulUI
    {
        /// <summary>
        /// UI 地址
        /// </summary>
        public string Address { get; set; }
        /// <summary>
        /// 数据中心
        /// </summary>
        public string Datacenter { get; set; }
    }

}

  

ConsulExtend 文件夹中的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Consul;
using ConsulCustomExtend.ConfigOptions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace ConsulCustomExtend.ConsulExtend
{
    public static class ConsulExtend
    {
        public static IServiceCollection AddConsul(this IServiceCollection services, IConfiguration config)
        {
            services.Configure<ConsulSettings>(config.GetSection("ConsulSettings"));
            services.AddScoped<ConsulClient>(sp =>
            {
                IOptionsSnapshot<ConsulSettings> options = sp.GetRequiredService<IOptionsSnapshot<ConsulSettings>>();
                ConsulSettings settings = options.Value;
                return new ConsulClient(config =>
                {
                    string addr = settings.ConsulUI.Address;
                    string datacenter = settings.ConsulUI.Datacenter;
                    config.Address = new Uri(addr);
                    config.Datacenter = datacenter;
                });
            });
            services.AddScoped<IConsulCustom, ConsulCustom>();
            return services;
        }


        public async static Task<IApplicationBuilder> UseConsul(this IApplicationBuilder app)
        {
            using var scope = app.ApplicationServices.CreateScope();
            ConsulSettings consulSettings = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<ConsulSettings>>().Value;
            using ConsulClient client = new ConsulClient(config =>
            {
                string addr = consulSettings.ConsulUI.Address;
                string datacenter = consulSettings.ConsulUI.Datacenter;
                config.Address = new Uri(addr);
                config.Datacenter = datacenter;

            });
            var registration = new AgentServiceRegistration
            {
                ID = Guid.NewGuid().ToString(),
                Address = consulSettings.ConsulSevice.Address,
                Name = consulSettings.ConsulSevice.Name,
                Tags = consulSettings.ConsulSevice.Tags,
                Port = consulSettings.ConsulSevice.Port,
                Check = new AgentServiceCheck
                {
                    HTTP = consulSettings.ConsulSevice.HealthCheck.HTTP, // "http://192.168.0.198:7777/health",///健康检查地址
                    Interval = TimeSpan.FromSeconds(consulSettings.ConsulSevice.HealthCheck.Interval)
                }
            };
            await client.Agent.ServiceRegister(registration);
            return app;
        }
    }
}

  

根目录下代码

using Consul;
using ConsulCustomExtend.ConfigOptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsulCustomExtend
{
    public class ConsulCustom : IConsulCustom
    {
        private readonly ConsulClient consulClient;
        public ConsulCustom(ConsulClient consulClient)
        {
            this.consulClient = consulClient;
        }
        /// <summary>
        /// 获取所有服务
        /// </summary>
        /// <returns></returns>
        public async Task<ServiceNode[]> GetServicesAllAsync()
        {
            var queryRuslt = await consulClient.Agent.Services();
            AgentService[] agentServices = queryRuslt.Response.Values.ToArray();
            ServiceNode[] serviceNodes = agentServices.Select(item => new ServiceNode
            {
                Address = item.Address,
                ID = item.ID,
                Port = item.Port,
                Name = item.Service,
                Tags = item.Tags

            }).ToArray();
            return serviceNodes;
        }
        public async Task<int> ReloadAsync()
        {
            string nodeName = consulClient.Agent.NodeName;
            WriteResult writeResult = await consulClient.Agent.Reload(nodeName);
            return (int)writeResult.StatusCode;
        }
        public async Task ServiceDeregisterAllAsync()
        {
            QueryResult<Dictionary<string, AgentService>> queryResult = await consulClient.Agent.Services();
            AgentService[] agentServices = queryResult.Response.Values.ToArray();
            foreach (var item in agentServices)
            {
                string serivceId = item.ID;
                await consulClient.Agent.ServiceDeregister(serivceId);
            }
        }
        public async Task<int> ServiceDeregisterAsync(string id)
        {
            WriteResult writeResult = await consulClient.Agent.ServiceDeregister(id);
            return (int)writeResult.StatusCode;
        }


        public async Task<int> ServiceRegisterAsync(ConsulSevice consulSevice)
        {
            var registration = new AgentServiceRegistration
            {
                ID = consulSevice.Id,
                Address = consulSevice.Address,//  "192.168.0.198",
                Name = consulSevice.Name, //"consultest",
                Tags = consulSevice.Tags, //new[] { "consultest" },
                Port = consulSevice.Port,// 7777,
                Check = new AgentServiceCheck
                {
                    HTTP = consulSevice.HealthCheck.HTTP,// "http://192.168.0.198:7777/health",///健康检查地址
                    Interval = TimeSpan.FromSeconds(consulSevice.HealthCheck.Interval)// TimeSpan.FromSeconds(3)
                }
            };
            WriteResult writeResult = await this.consulClient.Agent.ServiceRegister(registration);
            return (int)writeResult.StatusCode;
        }


        public void Dispose()
        {
            if (consulClient != null)
            {
                consulClient.Dispose();
                GC.SuppressFinalize(this);
            }
        }
    }
}

  

using ConsulCustomExtend.ConfigOptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsulCustomExtend
{
    public interface IConsulCustom:IDisposable
    {
        /// <summary>
        /// 获取所有服务 
        /// </summary>
        Task<ServiceNode[]> GetServicesAllAsync();

        /// <summary>
        /// 注销所有服务
        /// </summary>
        Task ServiceDeregisterAllAsync();
        /// <summary>
        /// 注销服务id
        /// </summary>
        /// <param name="id">服务id</param>
        /// <returns>注销返回状态码 200成功</returns>
        Task<int> ServiceDeregisterAsync(string id);
        /// <summary>
        /// 重新加载
        /// </summary>
        /// <returns>重新加载返回状态码 200成功</returns>
        Task<int> ReloadAsync();
        /// <summary>
        /// 服务注册
        /// </summary>
        /// <param name="consulSevice"></param>
        /// <returns>注册状态StatusCode</returns>
        Task<int> ServiceRegisterAsync(ConsulSevice consulSevice);

    }
}

  

 

using ConsulCustomExtend.ConfigOptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsulCustomExtend
{
    public interface IConsulCustom:IDisposable
    {
        /// <summary>
        /// 获取所有服务 
        /// </summary>
        Task<ServiceNode[]> GetServicesAllAsync();

        /// <summary>
        /// 注销所有服务
        /// </summary>
        Task ServiceDeregisterAllAsync();
        /// <summary>
        /// 注销服务id
        /// </summary>
        /// <param name="id">服务id</param>
        /// <returns>注销返回状态码 200成功</returns>
        Task<int> ServiceDeregisterAsync(string id);
        /// <summary>
        /// 重新加载
        /// </summary>
        /// <returns>重新加载返回状态码 200成功</returns>
        Task<int> ReloadAsync();
        /// <summary>
        /// 服务注册
        /// </summary>
        /// <param name="consulSevice"></param>
        /// <returns>注册状态StatusCode</returns>
        Task<int> ServiceRegisterAsync(ConsulSevice consulSevice);

    }
}

 

测试 ConsulWebAPI

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  //"AllowedHosts": "*",
  //"consul": {
  //  "address": "http://192.168.0.168:8500",
  //  "datacenter": "dc1"
  //},
  "ConsulSettings": {
    "ConsulUI": {
      "Address": "http://192.168.0.168:8500",
      "Datacenter": "dc1"
    },
    "ConsulSevice": {
      "Address": "192.168.0.198",
      "Name": "TS1",
      "Tags": ["userconsul"],
      "Port": 7777,
      "HealthCheck": {
        "HTTP": "http://192.168.0.198:7777/health",
        "Interval": 5
      }
    }
  }
}

  

using ConsulCustomExtend;
using Microsoft.AspNetCore.Mvc;
using ConsulCustom = ConsulCustomExtend.ConfigOptions;
namespace ConsulWebAPI.Controllers
{
    /// <summary>
    /// 测试封装Consul
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class TestConsulController : ControllerBase
    {
        private readonly IConsulCustom consulCustom;

        public TestConsulController(IConsulCustom consulCustom)
        {
            this.consulCustom = consulCustom;
        }
        /// <summary>
        /// 获取 所有服务
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetServicesAll")]
        public async Task<ActionResult> GetServicesAll()
        {
            ServiceNode[] serviceNodes = await this.consulCustom.GetServicesAllAsync();
            return Ok(serviceNodes);
        }

        /// <summary>
        /// 注销所有
        /// </summary>
        /// <returns></returns>
        [HttpGet("ServiceDeregister")]
        public async Task<ActionResult> ServiceDeregister()
        {
            await this.consulCustom.ServiceDeregisterAllAsync();
            return Ok();
        }

        /// <summary>
        /// 节点 刷新
        /// </summary>
        /// <returns></returns>
        [HttpGet("Reload")]
        public async Task<ActionResult> Reload()
        {
            int statusCode = await this.consulCustom.ReloadAsync();
            return Ok(statusCode);
        }

        /// <summary>
        /// 通过id服务注销
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("ServiceDeregister/{id}")]
        public async Task<ActionResult> ServiceDeregister([FromRoute] string id)
        {
            int statusCode = await this.consulCustom.ServiceDeregisterAsync(id);
            return Ok(statusCode);
        }
        /// <summary>
        /// 服务注册
        /// </summary>
        /// <returns></returns>
        [HttpPost("ServiceRegister")]
        public async Task<ActionResult> ServiceRegister( ConsulCustomExtend.ConfigOptions.ConsulSevice consulSevice)
        {
            int statusCode = await this.consulCustom.ServiceRegisterAsync(consulSevice);
            return Ok(statusCode);
        }
    }
}

  

using Consul;
using ConsulCustomExtend.ConsulExtend;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Reflection;
using System.Runtime.Intrinsics;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
    {
        Title = "consul测试",
        Description = "consul测试",
        Version = "v1",
    });
    string xmlPath = Assembly.GetExecutingAssembly().GetName().Name+".xml";
    string pathStr = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xmlPath);
    options.IncludeXmlComments(pathStr, true);
});

//注入 consul 扩展
builder.Services.AddConsul(builder.Configuration);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/v1/swagger.json ","v1");
    });
}

app.Map("/health", async next =>
{
    next.Response.StatusCode = (int)HttpStatusCode.OK;
    app.Logger.LogError($"{next.Request.Host}consul健康检查成功");
    await next.Response.WriteAsync("200");
});

//注册
//UseCustomConsulAsync();
//使用Consul注入
await app.UseConsul();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

async void UseCustomConsulAsync()
{
    using ConsulClient client = new ConsulClient(config =>
    {
        string addr = app.Configuration["consul:address"];
        string datacenter = app.Configuration["consul:datacenter"];
        config.Address = new Uri(addr);
        config.Datacenter = datacenter;

    });

    var registration = new AgentServiceRegistration
    {
        ID = Guid.NewGuid().ToString(),
        Address = "192.168.0.198",
        Name = "consultest",
        Tags = new[] { "consultest" },
        Port = 7777,
        Check = new AgentServiceCheck
        {
            HTTP = "http://192.168.0.198:7777/health",///健康检查地址
            Interval = TimeSpan.FromSeconds(3)
        }
    };
    await client.Agent.ServiceRegister(registration);
}

  

测试

 

 

最后 总结 封装的还是很顺利 Consul 主要是通过 Agent 进行 注册 ,和健康检查 这 从代码 上也能 体现出来

另外 app.ApplicationServices.GetRequiredService 是获取根容器上的 注入实例 单例模式是的实例是在根容器上 因为我注入的 是scope模式 所以 这样获取 会报错

要 创建 createscope 来获取 实例 这里 是一个技术点 

 

posted on 2023-11-25 09:08  是水饺不是水饺  阅读(14)  评论(0)    收藏  举报

导航