.net core集成使用consul
快速启动一个consul集群可以参考:使用docker快速部署一个consul集群
.net core集成使用consul是通过consul提供出来api接口来实现的,可以分成两个部分来说明:配置集成、服务注册。
代码比较多,已上传到gitee上了,地址见:https://gitee.com/shanfeng1000/dotnetcore-demo/tree/master/Consul
这是一个Demo项目,介绍.net core集成使用rabbitmq消息队列,使用的.net core 3.1,这里简单介绍:
集成使用Consul的kv store(配置服务)
.net core从consul的kv stroe中获取配置很容易,但是实现kv store的热加载有三种方式:
方式一:阻塞式查询(长轮询)(推荐)
有关阻塞式查询的介绍,可以参考官网:https://www.consul.io/api-docs/features/blocking
不过这里可以简单的将阻塞式查询理解为,consul为请求资源设置了一个index(可以理解为版本号),当资源更新时,consul会将版本号增加,而当使用api请求时可以携带一个index参数(起始版本)和wait参数(等待时间),当在wait时间内,存在index大于请求的index参数时(如果本就存在,那就不用等待了),会返回一个响应,响应会携带一个X-Consul-Index的Header,表示新的index,否则会在wait时间后超时返回响应,表示没有新的index。
在上面gitee的Demo中的AspNetCore.WebApi.Client中的Program中集成使用:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>(); ...
}).UseConsul(options =>
{
options.Address = "http://192.168.209.128:18401";
options.Datacenter = "dc1";
options.Token = "245d0a09";
options.Prefix = "Root/Consul"; //使用阻塞式查询实现热更新
options.Mode = WatchMode.Poll;
options.Interval = TimeSpan.FromMinutes(3);
});
现在consul中的kv store中Root/Consul节点下的所有kv都将被集成到.net core中的IConfiguration中去了,修改此节点下的任意kv都会自动更新IConfiguration,这是最简单的一种热更新方式。
方式二:consul watch
有关consul watch的介绍,可以参考官网:https://www.consul.io/docs/dynamic-app-config/watches
consul watch是一种监听机制,可以监听kv、service、node等信息,当它们发生改变时,触发某些handle,而这些handle包括执行shell脚本,发送http请求等。
事实上,consul watch是基于阻塞式查询的一种实现,但是遗憾的是,目前consul watch并没有提供出来api接口出来注册handle,所以在集成时,我们的项目需要提供出接口来公consul watch通知调用。
在上面gitee的Demo中的AspNetCore.WebApi.Server中的Program中集成使用:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
... webBuilder.ConfigureAppConfiguration(builder =>
{
builder.AddConsul(options =>
{
options.Address = "http://192.168.209.128:18401";
options.Datacenter = "dc1";
options.Token = "245d0a09";
options.Prefix = "Root/Consul"; //使用consul-template或者watch来实现热更新,需要在Configure中使用UseConsulWatch拦截更新配置请求
options.Mode = WatchMode.Watch;
options.ReloadName = "demo";
});
});
});
这样,项目启动后,可以从consul的kv store中读取配置,我们还需要提供一个回调的接口,可以在Startup的Configure方法时使用中间件UseConsulWatch来拦截:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseConsulWatch(); ...
}
默认情况下,这个接口是POST请求,地址是http://host:port/consul?name=reloadName,这里的reloadName就是在Program中配置的那个ReloadName,表示收到更新后,只会重新加载指定name名称的这个IConfigurationProvider,多个name之间使用逗号分隔。reloadName为空则表示重新加载所有的IConfigurationProvider,有了接口,接下来我们需要执行consul watch来启动监听:
# 执行consul watch
consul watch -http-addr=192.168.209.128:18402 -datacenter=dc1 -prefix=Root/Consul -type=keyprefix "curl -X POST http://192.168.28.212:16001/consul -d ''" 说明:
-http-addr:表示连接的consul地址,默认是127.0.0.1:8500
-datacenter:数据中心
-type:表示监听的类型,可选的有key, keyprefix, services, nodes, service, checks, event,这里是配置,所以选择keyprefix,表示具有这个前缀的所有kv(key表示单个的kv)
-prefix:kv的前缀
curl -X POST http://192.168.28.212:16001/consul -d '':这是kv更新后需要执行的命令,可以是shell脚本,也可以是普通的命令,这里是调用项目接口来更新项目配置实现热更新
现在,更新kv store,会发现程序已经实现了热加载
方式三:consul-template
有关consul-template相关的介绍可以参考:https://github.com/hashicorp/consul-template
consul-template的下载地址:https://releases.hashicorp.com/consul-template/
consul-template是基于consul watch的一套模板工具,可以这么理解consul-template,首先你需要提供一个模板,一般是一个ctmpl文件(语法类似于go template,具体可以参考这里)。接着,需要指定consul地址,及认证等信息,这样,consul-template连接到consul,然后会根据模板中需要的参数对consul进行监听,当对应的参数更新后会重新渲染模板。模板渲染更新后,我们可以使用这个新模板,一般我们先要将模板输出成文件才能使用(一般是配置文件),所以我们还需要指定一个输出文件路径。输出文件之后,我们还能需要执行一些脚本,命令等等。一般为了方便管理,这些配置都是写在一个config.hcl文件中。
.net core使用与上面consul watch一样,只是监听不在是使用consul watch,所以上面监听部分换成consul-template可以写成:
首先创建一个config.hcl文件:
consul {
address = "192.168.209.128:18402",
token = "245d0a09"
} template {
contents = "{{ tree \"Root/Consul\" | explode | toJSONPretty }}",
command = "curl -X POST http://192.168.28.212:16001/consul -d ''"
}
上面的contents及模板内容,这里的意思是以json格式输出Root/Consul下的kv,当Root/Consul下的kv更新时,会重新渲染这个模板,当然,contents的内容也可以写在一个ctmpl文件中,然后将contents换成source用于指定这个ctmpl文件的位置。command表示在模板渲染完成之后需要执行的命令,这里是使用curl发出一个http请求。更多配置说明参考:https://github.com/hashicorp/consul-template/blob/master/docs/configuration.md#configuration-file
现在可以使用consul-template来启动监控了:
# 启动
consul-template -config config.hcl -dry 说明:
-config:指定配置文件
-dry:表示渲染后的模板输出到标准输出中,而不是输出到一个文件中,如果没有这个参数,则需要在上面config.hcl中的temlate节点中添加一个destination节点,用于指明模板渲染后的输出文件路径,这里因为没使用到渲染后的文件,不需要使用文件,所以使用-dry输出即可
现在,更新kv store,会发现程序也已经实现了热加载。
注:
consul-template是一个很灵活的模板工具,我们可以将consul、consul-template、nginx一起使用,组合成一套服务自动发现功能:nginx使用consul-template生成conf文件,而consul-template监控consul中已经注册的服务,当有新实例加入或者已有实例退出时,consul-template会重新渲染生成新的conf文件,渲染完成后执行命令或者脚本让nginx重新加载即可。这种方式常常用在分布式系统的场景,因为如果我们的项目采用了分布式部署,难道要为分布式中的每个节点都手动的用consul watch?特别是容器化的应用,consul watch就不太现实了,这个时候可以使用consul-template来实现:
首先我们先创建一个ctmpl文件(如:demo.ctmpl):
#!/bin/bash #这行代码用于添加kv的监控
#{{ tree "Root/Consul" }} #输出server服务的所有实例,并请求重新加载配置
{{range service "server@dc1"}}
curl -X POST http://{{.Address}}:{{.Port}}/consul -d ''
{{end}}
接着创建一个demo.hcl文件:
consul {
address = "192.168.209.128:18402",
token = "245d0a09"
} template {
source = "./demo.ctmpl",
destination = "demo.sh",
command = "/bin/bash demo.sh"
}
然后启动:
# 启动,因为有输出文件,不能使用-dry
consul-template -config demo.hcl
这是,当名称为server的服务有多个实例时,kv 的更新会通知到所有的实例。(当然,这个例子中,配置加载采用这种方式也有缺点,因为新实例加入或者已有实例退出也会触发热加载)
使用Consul作为服务注册中心
consul是一款很优秀的服务治理工具,在这个demo项目中,我简单的做了一个封装,方便集成使用,如AspNetCore.WebApi.Client的Startup中的服务注册:
public void ConfigureServices(IServiceCollection services)
{
... //consul服务注册
services.AddConsulClient("consul", options =>
{
options.Address = "http://192.168.209.128:18401";
options.Datacenter = "dc1";
//options.Token = "token";//如果有token
}).AddService(options =>
{
options.Host = ip;
options.Port = port;
options.Id = $"client_{ip}_{port}";
options.Name = "client";
options.Tags = new[] { "client" };
options.HealthCheckPath = "Health";
}); ...
}
通过AddConsulClient方法创建一个Consul的客户端,通过AddService使用这个客户端添加服务,其中服务的健康检查支持简单的http和grpc两种方式,如果采用grpc方式,那么需要提供一个标准的grpc服务,官方给出的health.proto如下:
syntax = "proto3";
package grpc.health.v1; message HealthCheckRequest {
string service = 1;
} message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3;
}
ServingStatus status = 1;
} service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse); rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
注:此文件是官方标准,不要做任何改动,否则可能导致健康检查失败
Grpc方式的使用如AspNetCore.WebApi.Server的Startup中的服务注册:
public void ConfigureServices(IServiceCollection services)
{
... //consul服务注册
services.AddConsulClient(options =>
{
options.Address = "http://192.168.209.128:18405";
options.Datacenter = "dc1";
//options.Token = "token";//如果有token
}).AddService(options =>
{
//http服务
options.Host = ip;
options.Port = port;
options.Id = $"server_{ip}_{port}";
options.Name = "server";
options.Tags = new[] { "server" };
options.HealthCheckPath = "Health";
}).AddService(options =>
{
//grpc服务
options.Host = ip;
options.Port = grpcPort;
options.Id = $"server_grpc_{ip}_{grpcPort}";
options.Name = "server_grpc";
options.Tags = new[] { "server" };
//options.HealthCheckUrl = $"http://{ip}:{port}/Health";//使用http的健康检测 //使用grpc做健康检查
options.HealthCheckUseGrpc = true;
options.HealthCheckUrl = $"{ip}:{grpcPort}";//依赖health.proto
}); ...
}
AspNetCore.WebApi.Server的Startup中注册了两个服务,一个用于提供http服务,一个用于提供grpc服务,添加的服务,最终使用IHostedService来完成注册。
服务之间的通信通常采用http方式和grpc方式,如AspNetCore.WebApi.Client使用http和grpc两种方式调用AspNetCore.WebApi.Server服务,在AspNetCore.WebApi.Client的Startup中添加HttpClient和GrpcClient的客户端:
public void ConfigureServices(IServiceCollection services)
{
... //http client
services.AddHttpClient("http", client =>
{
client.BaseAddress = new Uri("http://server");//server是Server的http服务注册进Consul的服务名
}).AddServiceDiscovery("consul", LoadBalancerMode.RoundRobin);//添加服务发现机制 //grpc client
services.AddGrpcClient<WebApiServer.WebApiServerClient>("grpc", options =>
{
options.Address = new Uri("http://server_grpc");//server_grpc是Server的grpc服务注册进Consul的服务名
})
.AddServiceDiscoveryPolling(options =>//添加服务发现机制
{
options.Address = "http://192.168.209.128:18406";
options.Datacenter = "dc1";
//options.Token = "token";//如果有token
}); ...
}
AddHttpClient和AddGrpcClient就是你熟悉的那种调用方式,只是还添加了一个尾巴:AddServiceDiscovery和AddServiceDiscoveryPolling
AddServiceDiscovery:添加服务发现机制,服务名即请求地址中的host部分(不能携带端口),通知指定使用的consul客户端(如果是名称,则是使用AddConsulClient添加的客户端,也可以指定具体的consul信息),LoadBalancerMode是均衡模式,也就是说,当发起一个请求时,会将host部分作为服务名,使用指定的这个consul客户端去获取所有这个服务的实例,然后采用LoadBalancerMode指定的模式从这些实例中获得一个可用的实例,然后转而请求这个实例的资源。
AddServiceDiscoveryPolling:作用同AddServiceDiscovery,只是不在是每次请求都是使用consul客户端去获取服务实例,而是从实例缓存去获取可用的实例,这背后有一个定时器定时的去获取服务实例,然后刷新实例缓存,这样可以提高性能,但是不保证服务实例的可用性。
调用方式只需像原来的HttpClient和GrpcClient的方式去调用就可以了,如AspNetCore.WebApi.Client的RemoteController中的使用:
/// <summary>
/// 使用Http方式调用远程接口
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
public async Task<object> Http(string name)
{
var httpClientFactory = HttpContext.RequestServices.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient("http");//http是Startup中注册的http client名称
var response = await httpClient.GetAsync($"/Remote?name={name}");
return await response.Content.ReadAsStringAsync();
}
/// <summary>
/// 使用Grpc方式调用远程接口
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
public async Task<object> Grpc(string name)
{
var grpcClientFactory = HttpContext.RequestServices.GetRequiredService<GrpcClientFactory>();
var grpcClient = grpcClientFactory.CreateClient<WebApiServer.WebApiServerClient>("grpc");//grpc是Startup中注册的grpc client名称
var data = await grpcClient.SayAsync(new DataRequest() { Name = name });
return data.Message;
}
.net core集成使用consul的更多相关文章
- [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置
[翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置 原文: USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET COR ...
- NET Core + Ocelot + IdentityServer4 + Consul
.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现 先决条件 关于 Ocelot 针对使用 .NET 开发微服务架构或者面向服务架构提供一个统一访 ...
- asp.net core集成CAP(分布式事务总线)
一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...
- net core集成CAP
net core集成CAP https://www.cnblogs.com/guolianyu/p/9756941.html 一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET ...
- Net Core 中使用 Consul 来存储配置
Net Core 中使用 Consul 来存储配置 https://www.cnblogs.com/Rwing/p/consul-configuration-aspnet-core.html 原文: ...
- 【转】.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现
作者:Zhang_Xiang 原文地址:.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现 先决条件 关于 Ocelot 针对使用 .NET 开发 ...
- ABP官方文档翻译 6.2.1 ASP.NET Core集成
ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...
- asp.net core 集成 log4net 日志框架
asp.net core 集成 log4net 日志框架 Intro 在 asp.net core 中有些日志我们可能想输出到数据库或文件或elasticsearch等,如果不自己去实现一个 Logg ...
- [Abp 源码分析]十七、ASP.NET Core 集成
0. 简介 整个 Abp 框架最为核心的除了 Abp 库之外,其次就是 Abp.AspNetCore 库了.虽然 Abp 本身是可以用于控制台程序的,不过那样的话 Abp 就基本没什么用,还是需要集合 ...
随机推荐
- AI ubantu 环境安装
ubantu安装记录 apt install python3-pip anaconda安装 https://repo.anaconda.com/archive/Anaconda3-2020.11-Li ...
- zabbix之监控Nginx连接数
#;下载Nginx (编译的时候必须加上此选项 --with-http_stub_status_module) 官网地址:http://nginx.org/en/docs/http/ngx_http_ ...
- Spring(2):依赖注入DI
依赖注入DI 当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例.但在Spring里,创建被 ...
- linux查询健康状态,如何直观的判断你的Linux系统是否健康
一提到对于查看系统运行的健康状况,可能大多数朋友考虑到的就是查看进程或者打开任务管理器,但是对于应用在真实生产环境中服务器的linux系统来说,以上两种方式都不是***效的查看方式,那么今天就给大家推 ...
- vue 中使用import导入 script 在线链接
一般我们在vue中导入另外一个文件或者文件中的方法,我们都是使用import来实现他的,那么问题来了,现在我们要导入的不是另外的一个文件,而是在线链接,这该怎么办?我们也使用了 import * as ...
- 基于Annotation(注解)的装配
一.常用注解 1.@Component 是一种通用注解,可用于任何Bean 2.@Repository 通常用于注解DAO层类,即持久层 3.@Service 通常用于注解Service类,即服务层 ...
- 车载以太网第二弹|测试之实锤-TC8 TCP/IP协议一致性测试实践
前言 车载以太网测试实践系列,我们还分享了PMA测试实践.IOP测试实践 .本期给大家介绍的是TC8中的TCP/IP协议一致性测试(以下简称TCP/IP测试). TCP/IP测试-设备环境组成 TTw ...
- Charles ios设备抓包
在Mac下做开发,用Fiddler抓包由于离不开Windows比较痛苦,还好有Charles,到官网http://www.charlesproxy.com/可下载到最新版本(若不支持rMBP可拖到Re ...
- Win7远程连接问题:凭据不工作 & 没有授权此用户账户
一 您的凭据不工作 1.问题描述 win7系统远程桌面到某个电脑的一个账户名为admin 的用户,但提示"您的凭据不工作,之前连到 *.*.*.*的凭据无法使用,请输入新凭据",即 ...
- IO多路复用技术总结
来源:微信公众号「编程学习基地」 IO 多路复用概述 I/O 多路复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的 I/O 系统调用. 在IO多路复用技术 ...