快速启动一个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的更多相关文章

  1. [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置

    [翻译] 如何在 ASP.Net Core 中使用 Consul 来存储配置 原文: USING CONSUL FOR STORING THE CONFIGURATION IN ASP.NET COR ...

  2. NET Core + Ocelot + IdentityServer4 + Consul

    .NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现 先决条件 关于 Ocelot 针对使用 .NET 开发微服务架构或者面向服务架构提供一个统一访 ...

  3. asp.net core集成CAP(分布式事务总线)

    一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET Core 事件总线,分布式事务解决方案:CAP 以及 如何在你的项目中集成 CAP[手把手视频教程],之前也在工作中遇到分布式 ...

  4. net core集成CAP

    net core集成CAP https://www.cnblogs.com/guolianyu/p/9756941.html 一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET ...

  5. Net Core 中使用 Consul 来存储配置

    Net Core 中使用 Consul 来存储配置 https://www.cnblogs.com/Rwing/p/consul-configuration-aspnet-core.html 原文: ...

  6. 【转】.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现

    作者:Zhang_Xiang 原文地址:.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现 先决条件 关于 Ocelot 针对使用 .NET 开发 ...

  7. ABP官方文档翻译 6.2.1 ASP.NET Core集成

    ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...

  8. asp.net core 集成 log4net 日志框架

    asp.net core 集成 log4net 日志框架 Intro 在 asp.net core 中有些日志我们可能想输出到数据库或文件或elasticsearch等,如果不自己去实现一个 Logg ...

  9. [Abp 源码分析]十七、ASP.NET Core 集成

    0. 简介 整个 Abp 框架最为核心的除了 Abp 库之外,其次就是 Abp.AspNetCore 库了.虽然 Abp 本身是可以用于控制台程序的,不过那样的话 Abp 就基本没什么用,还是需要集合 ...

随机推荐

  1. AI ubantu 环境安装

    ubantu安装记录 apt install python3-pip anaconda安装 https://repo.anaconda.com/archive/Anaconda3-2020.11-Li ...

  2. zabbix之监控Nginx连接数

    #;下载Nginx (编译的时候必须加上此选项 --with-http_stub_status_module) 官网地址:http://nginx.org/en/docs/http/ngx_http_ ...

  3. Spring(2):依赖注入DI

    依赖注入DI 当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例.但在Spring里,创建被 ...

  4. linux查询健康状态,如何直观的判断你的Linux系统是否健康

    一提到对于查看系统运行的健康状况,可能大多数朋友考虑到的就是查看进程或者打开任务管理器,但是对于应用在真实生产环境中服务器的linux系统来说,以上两种方式都不是***效的查看方式,那么今天就给大家推 ...

  5. vue 中使用import导入 script 在线链接

    一般我们在vue中导入另外一个文件或者文件中的方法,我们都是使用import来实现他的,那么问题来了,现在我们要导入的不是另外的一个文件,而是在线链接,这该怎么办?我们也使用了 import * as ...

  6. 基于Annotation(注解)的装配

    一.常用注解 1.@Component 是一种通用注解,可用于任何Bean 2.@Repository 通常用于注解DAO层类,即持久层 3.@Service 通常用于注解Service类,即服务层 ...

  7. 车载以太网第二弹|测试之实锤-TC8 TCP/IP协议一致性测试实践

    前言 车载以太网测试实践系列,我们还分享了PMA测试实践.IOP测试实践 .本期给大家介绍的是TC8中的TCP/IP协议一致性测试(以下简称TCP/IP测试). TCP/IP测试-设备环境组成 TTw ...

  8. Charles ios设备抓包

    在Mac下做开发,用Fiddler抓包由于离不开Windows比较痛苦,还好有Charles,到官网http://www.charlesproxy.com/可下载到最新版本(若不支持rMBP可拖到Re ...

  9. Win7远程连接问题:凭据不工作 & 没有授权此用户账户

    一 您的凭据不工作 1.问题描述 win7系统远程桌面到某个电脑的一个账户名为admin 的用户,但提示"您的凭据不工作,之前连到 *.*.*.*的凭据无法使用,请输入新凭据",即 ...

  10. IO多路复用技术总结

    来源:微信公众号「编程学习基地」 IO 多路复用概述 I/O 多路复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的 I/O 系统调用. 在IO多路复用技术 ...