Consul服务注册与发现

Nginx+集群可以吗---可以—集群/负载均衡/水平扩展---但是不完美,就
是伸缩比较麻烦(能支持节点失效,但是不能自动感知新节点)---微服务架
构V1.0就是这个
Consul服务注册发现---更优秀一点---集群/负载均衡/水平扩展—自动注
册自动发现---心跳去发现缩减---微服务架构V2.0
Consul官网: https://www.consul.io
在官网下载consul压缩包后,解压 获得:consul.exe ,在该文件夹 cmd ,
执行: consul agent –dev ,这样启动consul

显示如图效果: 

在浏览器输入 http://localhost:8500/ ,显示如下图,说明consul运行起来了,再启动服务实例,将服务注册到consul中

 引入Consul内库后,写一个helper类

public static class ConsulHelper
{
    /// <summary>
    /// Consul注册
    /// </summary>
    /// <param name="configuration"></param>
    public static void ConsulRegist(this IConfiguration configuration)
    {
        ConsulClient client = new ConsulClient(c =>
        {
            c.Address = new Uri("http://localhost:8500/");
            c.Datacenter = "dc1";
        });//找到consul

        string ip = string.IsNullOrWhiteSpace(configuration["ip"]) ? "192.168.1.2" : configuration["ip"];
        int port = int.Parse(configuration["port"]);//命令行参数必须传入
        int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]);

        client.Agent.ServiceRegister(new AgentServiceRegistration()
        {
            ID = "service" + Guid.NewGuid(),//独一无二,
            Name = "UserService",//Group--分组--因为有多个实例组成的集群
            Address = ip,//
            Port = port,//
            Tags = new string[] { weight.ToString() },//标签
            Check = new AgentServiceCheck()
            {
                Interval = TimeSpan.FromSeconds(12),//间隔12s一次
                HTTP = $"http://{ip}:{port}/Api/Health/Index",//控制器
                Timeout = TimeSpan.FromSeconds(5),//检测等待时间
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(120)//失败后多久移除
            }
        });
        //命令行参数获取
        Console.WriteLine($"注册成功:{ip}:{port}--weight:{weight}");
    }
}

//启动时注册,且只注册一次
app.Configuration.ConsulRegist();

app.Run();

dotnet run --urls="http://*:5727" --ip=127.0.0.1 --port=5727 --
weight=10
dotnet run --urls="http://*:5728" --ip=127.0.0.1 --port=5728 --
weight=10
dotnet run --urls="http://*:5729" --ip=127.0.0.1 --port=5729 --
weight=10
dotnet run --urls="http://*:5730" --ip=127.0.0.1 --port=5730 --
weight=30
在项目的根目录启动四个进程,启动后,可以在consule浏览器看到多了几个服务,可以看到ip地址和端口,点开UserService后,进到里面可以看到有三个服务

 #region Consul
            //基于Consul去获取地址信息---只有IP:Port--然后调用
            string url = "http://UserService/api/users/all";
            ConsulClient client = new ConsulClient(c =>
            {
                c.Address = new Uri("http://localhost:8500/");
                c.Datacenter = "dc1";
            });//找到consul--像DNS
            var response = client.Agent.Services().Result.Response;//获取Consul全部服务清单

            Uri uri = new Uri(url);
            string groupName = uri.Host;
            AgentService agentService = null;
            var dictionary = response.Where(s => s.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray();
            {
                //agentService = dictionary[0].Value;//写死第一个 
            }
            {
                轮询
                //agentService = dictionary[iIndex++ % dictionary.Length].Value;
            }
            {
                随机策略--也就是平均一下
                //agentService = dictionary[new Random(iIndex++).Next(0, dictionary.Length)].Value;
            }
            {
                //权重策略---能为不同的进程指定不同的权重值,根据权重值分配请求数
                List<KeyValuePair<string, AgentService>> pairsList = new List<KeyValuePair<string, AgentService>>();
                foreach (var pair in dictionary)
                {
                    int count = int.Parse(pair.Value.Tags?[0]!);//1  10   30
                    for (int i = 0; i < count; i++)
                    {
                        pairsList.Add(pair);
                    }
                }
                //41个  
                agentService = pairsList.ToArray()[new Random(iIndex++).Next(0, pairsList.Count())].Value;
            }

            url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}";
            string content = this._iHttpAPIInvoker.InvokeApi(url); //InvokeApi(url);
            base.ViewBag.Users = JsonConvert.DeserializeObject<IEnumerable<User>>(content);
            Console.WriteLine($"This is {url} Invoke");
            #endregion
这时候还需要写一段代码,进行心跳检测
 public static class HealthCheckMiddlewareExtension
    {
        /// <summary>
        /// 设置心跳响应
        /// </summary>
        /// <param name="app"></param>
        /// <param name="checkPath">默认是/Health</param>
        /// <returns></returns>
        public static void UseHealthCheckMiddleware(this IApplicationBuilder app, string checkPath = "/Health")
        {
            app.Map(checkPath, applicationBuilder => applicationBuilder.Run(async context =>
            {
                Console.WriteLine($"This is Health Check");
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                await context.Response.WriteAsync("OK");
            }));
        }

    }

再把这段代码在管道里注册

app.UseHealthCheckMiddleware("/Api/Health/Index");

1.客户端跟Consul交互,获取服务清单
2 解析替换,得到完整地址,进行服务调用
3 负载均衡策略实现---选择一下调用哪一个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值