.net core consul 服务配置 服务发现 服务健康检测 服务变更加载
准备环境
安装consul之后
1. 创建一个.net core webapi 举例为UsercenterService
2. nuget引用Consul组件 https://github.com/PlayFab/consuldotnet
3. 创建配置实体类 (后面涉及功能介绍时候再解释属性含义)
public class AppSettings
{
/// <summary>
/// 数据库连接字符串
/// </summary>
public string DbConnection { get; set; } /// <summary>
/// 服务注册参数
/// </summary>
public ServiceRegisterOptions ServiceRegisterOptions { get; set; }
} public class ServiceRegisterOptions
{
/// <summary>
/// 是否启用
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// 服务名称
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// 服务IP或者域名
/// </summary>
public string ServiceHost { get; set; }
/// <summary>
/// 服务端口号
/// </summary>
public int ServicePort { get; set; }
/// <summary>
/// consul注册地址
/// </summary>
public string ConsulRegisterUrl { get; set; }
/// <summary>
/// 标签 例如laiwutest
/// </summary>
public string[] Tags { get; set; }
}
4. appsettings配置consul服务地址和UserService配置在consul的节点key
4.1 配置consul地址(举例是在VS调试开发环境。所以在appsettings.Development.json中配置)
{
"ConsulForConfig": {
"Host": "{IP}:8500",//这里替换成自己consul服务的IP地址
"Prefix": "git-dev/huangqiang/usercenterRegionIIS.json"
}
}
4.2 在consul上创建该节点并且配置
{
"DbConnection": "",
"ServiceRegisterOptions":
{
"IsActive":true,
"ServiceName":"UserCenterRegion",
"ServiceHost":"{IP}",//修改{IP}为你注入的服务的ip地址
"ServicePort":"{Port}",//修改{Port}为你注入的服务的端口
"ConsulRegisterUrl":"{IP}:8500",//修改{IP}为你的consul服务的IP
"Tags":["浙江杭州"]
},
}
获取配置
public static AppSettings AddAppSettingByConsul(this IServiceCollection sc, IConfiguration configuration)
{
try
{
//get local consul service address configration consulclient
var consulAddress = $"http://" + configuration["ConsulForConfig:Host"];
var key = configuration["ConsulForConfig:Prefix"];
if (string.IsNullOrWhiteSpace(consulAddress) || string.IsNullOrWhiteSpace(key))
{
throw new Exception("无法获取consulAddress地址或者consul key");
}
var consulClient = new ConsulClient(cfg => { cfg.Address = new Uri(consulAddress); });
sc.AddSingleton<IConsulClient>(p => consulClient);
//get app config
var res = consulClient.KV.Get(key).GetAwaiter().GetResult();
var resStr = Encoding.UTF8.GetString(res.Response.Value);
var appSettings = JsonConvert.DeserializeObject<AppSettings>(resStr);
if (appSettings == null)
{
throw new Exception($"appSettings 为null,consul 配置:{resStr}");
}
sc.AddSingleton<AppSettings>(appSettings);
return appSettings;
}
catch (Exception e)
{
_log.Main.Error($"获取consul appsettings配置异常:{e.Message}");
Environment.Exit(-);
}
return null;
}
这里抽了一个扩展方法。使用的时候在Startup.cs类中的方法ConfigureServices中加入,这里弄了返回值只是偷懒下。
AddAppSettingByConsul方法逻辑:先是拿到配置的consull服务地址和Key,再通过前面nuget引用的consul组件中的consulclient获取配置,最后注入到容器
调试下 就拿到配置了。这样方便分布式服务,不用每台都配置,直接consul管理
配置健康检测和服务注册
准备健康检测接口:
[Route("api/v1/[controller]")]
[ApiController]
public class HealthController : ControllerBase
{
[HttpGet]
public IActionResult Get() => Ok("ok");
}
.net core 配置注册和健康检测的地址
public static void UseConsul(this IApplicationBuilder app, IApplicationLifetime appLife)
{
try
{
var appSettings = app.ApplicationServices.GetService<AppSettings>();
var consulClient = app.ApplicationServices.GetService<IConsulClient>(); //config consul health check
var healthCheck = new AgentServiceCheck
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(),
Interval = TimeSpan.FromSeconds(),
HTTP = $"{appSettings.ServiceRegisterOptions.ServiceHost}:{appSettings.ServiceRegisterOptions.ServicePort}/api/v1/Health",
}; //service register
var serviceId = $"{appSettings.ServiceRegisterOptions.ServiceName}_{appSettings.ServiceRegisterOptions.ServiceHost}:{appSettings.ServiceRegisterOptions.ServicePort}";
var registration = new AgentServiceRegistration
{
Checks = new[] { healthCheck },
Address = appSettings.ServiceRegisterOptions.ServiceHost,
Port = appSettings.ServiceRegisterOptions.ServicePort,
ID = serviceId,
Name = appSettings.ServiceRegisterOptions.ServiceName,
Tags = appSettings.ServiceRegisterOptions.Tags
};
consulClient.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); //service Deregister when app stop
appLife.ApplicationStopped.Register(() =>
{
consulClient.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult();
}); }
catch (Exception e)
{
_logger.Main.Error($"UseConsul error:{e.Message}");
Environment.Exit(-);
} }
这里也是抽了个扩展方法。调用放到Startup
UseConsul方法解释:先是从容器中拿到前面注入的配置实体AppSettings和ConsulClient。再配置健康检测,再配置服务注册,再配置当服务关闭时候注销服务。
其中健康检测的DeregisterCriticalServiceAfter表示如果服务启动失败,多少时间内注销consul上的该服务。
服务注册的参数就不介绍了
然后跑起来之后,到consul ui瞧一瞧。是不是注册成功,心跳正常
状态为passing为正常的,刚启动时候状态会为critical。 当你的状态一直为critical时候,过了前面DeregisterCriticalServiceAfter的时间,服务将会注销,也就是注册失败。可能原因:服务地址配置有问题,consul无法访问你的health地址,也可能你的端口没打开。telnet看看
当都成功的时候,服务已经正常注册到consul。下面再说说服务发现和服务变更发现
服务发现和服务变更发现
服务发现调用的方法有很多,agent,catalog,health,都可以获取列表。但是agent是查询本地自己的,catalog是整个集群的,heath是查询健康的。这里用health获取举例
关键就一句话:_consulClient.Health.Service(serviceName, tag, true, queryOptions).Result。
这样就能获取到注册到consul的服务列表了,但是如果有服务变更了(新的服务注册,旧的服务停止),应该怎么办?
一般想到启动一个线程不停的去拿,是没有问题,但是有个更好的东西,“Blocking Queries” https://www.consul.io/api/index.html
这个东西简单来说就是会记录一个版本,consul服务端通过这个版本来判断是不是已经是最新的服务列表,如果是的话,那么将会阻塞一定时间(这个时间可配置)
在c# 里面体现就是第三个参数queryOptions的WaitIndex和WaitTime,以及返回LastIndex,下面po出一部分代码。
public void GetAllService()
{
_serviceIndexList.ForEach(p =>
{
Task.Run(() =>
{
var queryOptions = new QueryOptions { WaitTime = TimeSpan.FromSeconds(_waitTime) };
while (true)
{
GetAgentServices(queryOptions, p.ServiceName, p.Tag);
}
});
});
} public void GetAgentServices(QueryOptions queryOptions, string serviceName, string tag = null)
{
try
{
var res = _consulClient.Health.Service(serviceName, tag, true, queryOptions).Result;
_logger.Main.Info($"GetServiceList:{serviceName} {tag} waitIndex:{res.LastIndex}");
if (queryOptions.WaitIndex != res.LastIndex)
{
queryOptions.WaitIndex = res.LastIndex;
var currentService = _consulServices.FirstOrDefault(p => p.ServiceName == serviceName);
if (currentService == null)
{
_consulServices.Add(new ConsulService
{
ServiceName = serviceName,
Tag = tag,
ServiceEntries = new ConcurrentBag<ServiceEntry>(res.Response)
});
}
else
{
currentService.ServiceEntries = new ConcurrentBag<ServiceEntry>(res.Response);
}
}
}
catch (AggregateException ae)
{
_logger.Main.Error($"consul获取{serviceName},{tag}服务列表资源错误:{ae.Flatten()}",ae);
}
catch (Exception e)
{
_logger.Main.Error($"consul获取{serviceName},{tag}服务列表资源错误",e);
}
}
注:代码中的_serviceIndexList是存着需要获取哪些服务的服务tag,_consulServices是程序维护的最新服务列表
.net core consul 服务配置 服务发现 服务健康检测 服务变更加载的更多相关文章
- .Net Core 商城微服务项目系列(二):使用Ocelot + Consul构建具备服务注册和发现功能的网关
1.服务注册 在上一篇的鉴权和登录服务中分别通过NuGet引用Consul这个包,同时新增AppBuilderExtensions类: public static class AppBuilderEx ...
- (8)ASP.NET Core3.1 Ocelot Consul服务注册与发现
1.服务注册与发现(Service Discovery) ●服务注册:我们通过在每个服务实例写入注册代码,实例在启动的时候会先去注册中心(例如Consul.ZooKeeper.etcd.Eureka) ...
- Consul初探-服务注册和发现
前言 经过上一篇的学习,现在已经来到了服务注册发现环节:Consul 的核心功能就是服务注册和发现,Consul 客户端通过将自己注册到 Consul 服务器集群,然后等待调用方去发现服务,实现代理转 ...
- 一个故事,一段代码告诉你如何使用不同语言(Golang&C#)提供相同的能力基于Consul做服务注册与发现
目录 引言 什么是微服务 传统服务 微服务 什么是服务注册与服务发现 为什么要使用不同的语言提供相同的服务能力 服务协调器 服务注册 Golang C#(.NetCore3.1) 服务发现 通过Htt ...
- Docker consul的容器服务更新与发现(超详细配图)
Docker consul的容器服务更新与发现 1.概述 2.部署 1.概述: (1)什么是服务注册与发现: 服务注册与发现是微服务架构中不可或缺的重要组件.起初服务都是单节点的,不保障高可用性,也不 ...
- AgileConfig 1.6.0 发布 - 支持服务注册与发现
大家好,好久没有输出博文了,一是因为比较忙,另外一个原因是最近主要的精力是在给 AgileConfig 添加一个新的功能:服务注册与发现. 先说说为什么会添加这个功能.我自己的项目是用 Consul ...
- springcloud之服务注册与发现(zookeeper注册中心)-Finchley.SR2版
新年第一篇博文,接着和大家分享springcloud相关内容:本次主要内容是使用cloud结合zookeeper作为注册中心来搭建服务调用,前面几篇文章有涉及到另外的eureka作为注册中心,有兴趣的 ...
- SpringCloud(3)---Eureka服务注册与发现
Eureka服务注册与发现 一.Eureka概述 1.Eureka特点 (1) Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移. (2) Eureka 主管服务 ...
- SpringCloud-Eureka服务注册与发现(二)
SpringCloud-Eureka服务注册与发现(二) https://www.cnblogs.com/qdhxhz/p/9357502.html https://blog.csdn.net/wei ...
随机推荐
- PHP金钱数字转金钱大写
/* * 数字金额转换成中文大写金额的函数 * String Int $num 要转换的小写数字或小写字符串 * return 大写数字 */ function num_to_rmb($num){ $ ...
- 将本地代码备份到Github public repository
1. 在本地代码所在的文件夹中初始化,即打开powershell,输入下面命令 git init 此时本地文件夹中会出现一个`.git`的隐藏文件夹. 2. 然后将当前的文档`commit`,在本 ...
- Linux-共享内存通信
Linux共享存储通信 内容 创建共享存储区实现进程通信 机理说明 共享存储区(Share Memory)是Linux系统中通信速度最高的通信机制.该机制中共享内存空间和进程的虚地址空间满足多对多的关 ...
- window.open在ajax里 被浏览器拦截
setLine(row){ let newTab= window.open('about:blank'); this.api.isPrivilege(localStorage.getItem(&quo ...
- NOIP-接水问题
题目描述 学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1. 现在有n名同学准备接水,他们的初始接水顺序已经确定.将这些同学按接水顺序从1到n编号,i号同学 ...
- Spring SpringMVC SpringBoot SpringCloud概念、关系及区别
一.正面解读: Spring主要是基于IOC反转Beans管理Bean类,主要依存于SSH框架(Struts+Spring+Hibernate)这个MVC框架,所以定位很明确,Struts主要负责表示 ...
- mysql8.0.13修改密码
在安装完数据库后,由于自己不小心直接关闭了安装窗口,或者长时间没有使用root用户登录系统,导致忘记了root密码,这时就需要重置MySQL的root密码.当然,最简单方式自然是删除数据库的data目 ...
- 自己封装element-ui树组件的过滤
前言:vue开发项目时用到了element-ui的树组件,但是发现一执行过滤事件,树就全部都展开了,为了解决这个问题,只能自己先过滤数剧,再赋值给树组件的data,就避免了一上来全部展开的尴尬. 一. ...
- Hadoop集群搭建-HA高可用(手动切换模式)(四)
步骤和集群规划 1)保存完全分布式模式配置 2)在full配置的基础上修改为高可用HA 3)第一次启动HA 4)常规启动HA 5)运行wordcount 集群规划: centos虚拟机:node-00 ...
- 神经网络_线性神经网络 1 (Nerual Network_Linear Nerual Network 1)
2019-04-08 16:59:23 1 学习规则(Learning Rule) 1.1 赫布学习规则(Hebb Learning Rule) 1949年,Hebb提出了关于神经网络学习机理的“突触 ...