快速启动一个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. 【简】题解 AWSL090429 【聚会】

    这题直接换根dp 记录在要转移的点的子树中有多少牛 #include<bits/stdc++.h> using namespace std; #define ll long long #d ...

  2. cmd窗口连接mongodb服务端

    1----->配置环境变量,将mongodb\bin目录配置到path 2----->打开cmd窗口,进入到bin目录,测试mongodb服务端是否在运行:net start mongod ...

  3. mrctf2020_shellcode_revenge(可见符shellcode)!!!!

    第一次碰到这种题目,需要用可见符shellcode来做 题目我就不放了,我认为网上大佬会比我说的更加详细 [原创]纯字母shellcode揭秘-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pedi ...

  4. Google earth engine 绘制图像间散点图

    这段代码实现了在Google earth engine中绘制图像/波段间的散点图,得到相关关系.适用于探究数据间的相关性,进行数据的交叉验证. 代码来源于官方帮助:https://developers ...

  5. Python 线程池模块threadpool 、 concurrent.futures 的 ThreadPoolExecutor

    一.threadpool   基本用法 pip install threadpool pool = ThreadPool(poolsize) requests = makeRequests(some_ ...

  6. curl -w参数简析

    curl的-w参数用于在一次完整且成功的操作后输出指定格式的内容到标准输出. 输出格式由普通字符串和任意数量的变量组成,输出变量需要按照%{variable_name}的格式,如果需要输出%,doub ...

  7. bootstrap栅格例子

    <div class="container-fluid "> <div class="row"> <div class=" ...

  8. myeclipse 安装spket

    myeclipse 安装spket为以下步骤 请注意:1.myPlugins为新建的文件夹 2.spket-1.6.23为新建的文件 如上步骤为安装spket,那么如下的步骤为让myeclipse里的 ...

  9. Jenkins安装部署使用图文详解(非常详细)

    前言 最近公司需要弄一套自动化运维部署,于是抽空学习了一下,用了两天左右完成Jenkins的安装部署和各种项目的配置化,于是整理一下进行分享. 介绍 Jenkins是一个独立的开源软件项目,是基于Ja ...

  10. 『学了就忘』Linux日志管理 — 92、日志轮替

    目录 1.日志文件的命名规则 2.logrotate配置文件说明 3.logrotate配置文件的主要参数 1.日志文件的命名规则 日志轮替最主要的作用就是把旧的日志文件移动并改名,同时建立新的空日志 ...