基于.net core 开发的轻量级配置中心 - AgileConfig

AgileConfig 简介

是一个基于 .net core 开发的轻量级配置中心。

目标或解决的问题

AgileConfig 并不是为了什么微服务,更多的是为了那些分布式、容器化部署的应用能够更加简单的读取、修改配置。

AgileConfig 特点

秉承轻量化的,部署简单、配置简单、使用简单、学习简单,它只提取了必要的一些功能,并没有像 Apollo 那样复杂且庞大。但是它的功能也已经足够你替换 web.config,appsettings.json 这些文件了。

如果你不想用微服务全家桶,不想为了部署一个配置中心而需要看 N 篇教程跟几台服务器那么你可以试试 AgileConfig。

  • 部署简单,最少只需要一个数据节点,支持docker部署
  • 支持多节点分布式部署来保证高可用
  • 配置支持按应用隔离,应用内配置支持分组隔离
  • 支持多环境
  • 应用支持继承,可以把公共配置提取到一个应用然后其它应用继承它
  • 使用长连接技术,配置信息实时推送至客户端
  • 支持 IConfiguration,IConfigClient,IOptions 模式读取配置,原程序几乎可以不用改造
  • 配置修改支持版本记录,随时回滚配置
  • 如果所有节点都故障,客户端支持从本地缓存读取配置
  • 支持Restful API维护配置
  • v-1.6.0 以上已支持服务注册与发现

参考地址

  • Github:https://github.com/dotnetcore/AgileConfig
  • Gitee:https://gitee.com/kklldog/AgileConfig
  • AgileConfig releases:https://github.com/dotnetcore/AgileConfig/releases
  • AgileConfig Change log:https://github.com/dotnetcore/AgileConfig/blob/master/CHANGELOG.md
  • Docker 镜像:https://hub.docker.com/r/kklldog/agile_config
  • 作者博客:https://www.cnblogs.com/kklldog/p/agile-config.html

AgileConfig 架构介绍

AgileConfig的架构比较简单,主要是分3块:

基于.net core 开发的轻量级配置中心 - AgileConfig_第1张图片

客户端(Client)

客户端程序是使用 netstandard2.0 开发的一个类库,方便 .net core 程序接入,nuget 搜AgileConfig.Client 就可以安装。可以在启动客户端的时候配置多个节点的地址,客户端会随机挑选一个进行连接,连接成功后会维持一个websocket长连接。如果连接的节点发生故障导致连接中断,客户端会继续随机一个节点进行连接,直到连接成功。

节点、管理程序(Node Server、Console)

节点是使用 asp.net core 开发的一个服务。为了部署简单,直接把管理程序跟节点服务合二为一了。任何一个节点都可以在启动的时候配置环境变量开启管理程序功能。

数据库(Database)

使用数据库来存储数据,目前支持Sqlserver, Mysql, Sqlite, PostgreSql, Oracle 五种数据库。最新版本已经切换为Freesql为数据访问组件。Freesql对多数据库的支持更加强劲,特别是对国产数据库的支持。但是因为没有国产数据库的测试环境,本项目并未支持,如果有需要我可是开分支尝试支持,但是测试工作就要靠用户啦。

注意:如果使用 <=1.0.4 之前版本的用户请不要更新,因为 EFCore 跟 FreeSql 自动建的库可能存在稍许差异,保险起见不要更新吧。

关于高可用

AgileConfig 的节点都是无状态的,所以可以横向部署多个节点来防止单点故障。在客户端配置多个节点地址后,客户端会随机连接至某个节点。

问题 影响 说明
控制台下线 无法维护配置,客户端无影响 因为控制台跟节点是共存的,所以某个控制台下线一般来说同样意味着一个节点的下线
某个节点下线 客户端重连至其他节点 无任何影响
所有节点下线 客户端从内存读取配置 启动的客户端会从内存读取配置,未启动的客户端会再尝试连接到节点多次失败后,尝试从本地文件缓存读取配置,保证应用可以启动

注意:结合 DB 数据库的高可用技术搭配使用。

AgileConfig 服务端搭建

初始化 DB 数据库

用户只需要手工建一个空库,所有的表在第一次启动的时候都会自动生成。目前支持 SqlServer,MySQL,Sqlite, PostgreSQL,Oracle 五种数据库。

基于.net core 开发的轻量级配置中心 - AgileConfig_第2张图片
docker 运行服务端项目即可初始化对应的数据库,此处以 PostgreSQL 数据库为例。

DB Provider 对照表

数据名称:agile_config,用户:chait,密码:123456

db provider db type 连接字符串
sqlserver SQL Server Data Source=127.0.0.1,1433;Initial Catalog=agile_config;User Id=chait;Password=123456;TrustServerCertificate=true;Pooling=true;Max Pool Size=50
mysql MySQL Data Source=127.0.0.1;Port=3306;Initial Catalog=agile_config;User ID=chait;Password=123456;Charset=utf8mb4;SslMode=none;Max pool size=50
sqlite Sqlite Data Source=agile_config.db;Version=3;UseUTF16Encoding=True;Password=123456;Pooling=true;FailIfMissing=false;Max Pool Size=50
npgsql PostgreSQL Server=127.0.0.1;Port=5432;Database=agile_config;Username=chait;Password=123456;Pooling=true;Maximum Pool Size=50
oracle Oracle Data Source=//127.0.0.1:1521/XE;User Id=chait;Password=123456;Pooling=true;Max Pool Size=50

Docker 部署服务端

docker run 命令运行服务端

  • 拉取 agile_config 镜像
docker pull kklldog/agile_config:latest
  • 运行 agile_config 容器
sudo docker run \
 --name agile_config \
 -e TZ=Asia/Shanghai \
 -e adminConsole=true \
 -e db:provider=sqlite \
 -e db:conn="Data Source=agile_config.db;Version=3;UseUTF16Encoding=True;Password=123456;Pooling=true;FailIfMissing=false;Max Pool Size=50" \
 -p 15000:5000 \
 -v /agileconfig:/app/db \
 -d \
 kklldog/agile_config:latest

参数说明

  • name:容器名,指定个容器名。
  • TZ:指定时区。
  • adminConsole:配置程序是否使用管理控制台。如果为true则启用控制台功能,访问该实例会出现管理界面。
  • 每个实例都可以选择使用管理界面,共用一套数据源只是呈现端口不同。默认账号为 admin,首次登录需要设置密码,设置后多个管理界面都可以通用。
  • db:provider:配置程序的数据库类型。目前程序支持:sqlite,mysql,sqlserver,npgsql, oracle 五种数据库。按照项目中允许的数据库使用即可。首个节点启动后会创建数据表(相当好~)。
  • db:env:{env}:provider,可以指定特定环境下使用某个数据库,如【db:env:PROD.provider=sqlserver, db:env:DEVELOPMENT.provider=mysql】。
  • db:conn:配置数据库连接串。按照不同的数据库类型设置不同的数据库连接字符串。
    数据库使用第二步创建的库。 默认内置了 DEV, TEST, STAGING, PROD 四个常用的环境,如不够,可直接操作 agc_setting 表,增加自定义环境。
  • db:env:{env}:conn,可以指定特定环境下使用某个数据库,如 【db:env:PROD.conn=xxx, db:env:DEVELOPMENT.conn=xxx】。
  • p:指定对外端口,用户客户端去连接。设置允许使用的对外端口即可。
  • v:节点的数据卷挂载。此处挂载到第一步设置的文件夹路径下,可按实际需要设置挂载路径或是不设置 -v 参数也行。
  • -d:设置容器后台运行。

通过 docker 建立一个 agile_config 容器实例,其中有 3 个环境变量需要配置:

  • adminConsole 配置程序是否为管理控制台。如果为 true 则启用控制台功能,访问该实例会出现管理界面。
  • db:provider 配置程序的数据库类型。目前程序支持:sqlite,mysql,sqlserver,npgsql,oracle 五种数据库。
  • db:conn 配置数据库连接串。

docker compose 运行服务端

除了上面的 docker run 的方式运行 agile_config 容器实例,还可以使用 docker compose 来快速创建,此处以 postgresql 数据库为例,编写 yaml 文件如下:

version: '3'
services:
  agile_config_admin:
    image: "kklldog/agile_config:latest"
    ports:
      - "15000:5000"
    networks:
      - net0
    volumes:
      - /etc/localtime:/etc/localtime
    environment:
      - TZ=Asia/Shanghai
      - adminConsole=true
      - nodes=agile_config_admin:5000,agile_config_node1:5000,agile_config_node2:5000
      - db:provider=npgsql
      - db:conn= Server=Server=127.0.0.1;Port=5432;Database=agile_config;Username=chait;Password=123456;Pooling=true;Maximum Pool Size=50
  agile_config_node1:
    image: "kklldog/agile_config:latest"
    ports:
      - "15001:5000"
    networks:
      - net0
    volumes:
      - /etc/localtime:/etc/localtime
    environment:
      - TZ=Asia/Shanghai
      - db:provider=npgsql
      - db:conn= Server=127.0.0.1;Port=5432;Database=agile_config;Username=chait;Password=123456;Pooling=true;Maximum Pool Size=50
    depends_on:
      - agile_config_admin
  agile_config_node2:
    image: "kklldog/agile_config:latest"
    ports:
      - "15002:5000"
    networks:
      - net0
    volumes:
      - /etc/localtime:/etc/localtime
    environment:
      - TZ=Asia/Shanghai
      - db:provider=npgsql
      - db:conn= Server=127.0.0.1;Port=5432;Database=agile_config;Username=chait;Password=123456;Pooling=true;Maximum Pool Size=50
    depends_on:
      - agile_config_admin
networks:
  net0:

注意:如果通过 IIS 或者别的方式部署,请自行从主页上的 releases 页面下载最新的部署包。如果自己使用源码编译,请先编译 react-ui-antd 项目把 dist 内的产物复制到 apisite 项目的 wwwroot/ui 目录下。

浏览器查看 AgileConfig 管理界面

浏览器输入如下地址:

http://localhost:15000/ui#/user/login
http://localhost:15000/ui#/home

看到如下界面,说明 AgileConfig 服务端已经部署成功。

基于.net core 开发的轻量级配置中心 - AgileConfig_第3张图片

注意:第一次运行程序需要初始化管理员密码。

AgileConfig 管理界面介绍

基于.net core 开发的轻量级配置中心 - AgileConfig_第4张图片

菜单说明

菜单 说明
首页 显示一些相关指标的统计数据。
节点 AgileConfig 支持多节点部署,所有的节点都是平行的。为了简化部署,AgileConfig 并没有单独的控制台程序,请直接使用任意一个节点作为控制台。当环境变量 adminConsole=true 时,该节点同时兼备数据节点跟控制台功能。为了控制台能够管理节点,所以需要在控制台配置节点的信息。
注意:即使是作为控制台的数据节点同样需要添加到管理程序,以便管理它。
应用 AgileConfig 支持多应用程序接入。需要为每个应用程序配置名称、ID、秘钥等信息。每个应用可以设置是否可以被继承,可以被继承的应用类似 apollo 的公共 namespace 的概念。
公共的配置可以提取到可继承应用中,其它应用只要继承它就可以获得所有配置。
如果子应用跟被继承应用之间的配置键发生重复,子应用的配置会覆盖被继承的应用的配置。子应用可以继承多个应用,如果多个应用之间发生重复键,按照继承的顺序,后继承的应用的配置覆盖前面的应用。
配置项 配置完应用信息后可以为每个应用配置配置项。配置项支持分组。新添加的配置并不会被客户端感知到,需要手工点击“上线”才会推送给客户端。已上线的配置如果发生修改、删除、回滚操作,会实时推送给客户端。版本历史记录了配置的历史信息,可以回滚至任意版本。
客户端 控制台可以查看已连接的客户端。
日志 系统日志记录了 AgileConfig 生产中的一些关键信息。
用户 可以添加管理配置中心的用户人员信息,用户组,角色。

AgileConfig 客户端使用

查看 nuget 包 =》https://www.nuget.org/packages/AgileConfig.Client/

基于.net core 开发的轻量级配置中心 - AgileConfig_第5张图片

新建 asp.net core webapi 项目,并添加 nuget 包【AgileConfig.Client】

  • 新建项目 WebApplication.AgileConfig ,项目结构如下:

基于.net core 开发的轻量级配置中心 - AgileConfig_第6张图片

注意:chait.agileconfig.client.configs.cache 该文件是本地缓存文件,运行项目后生成。

  • 在新建项目添加 nuget 包 AgileConfig.Client
Install-Package AgileConfig.Client -Version 1.6.1
  • 修改 appsettings.json/appsettings.Development.json 配置文件,添加 AgileConfig 配置
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  //agile_config
  "AgileConfig": {
    "appId": "chait",
    "secret": "xxx",
    "nodes": "http://192.168.10.251:15000,http://192.168.10.251:15001,http://192.168.10.251:15002", //多个节点使用逗号分隔,
    "name": "client_name",
    "tag": "tag1",
    "env": "DEV",
    "httpTimeout": "100",
    "cache": {
      "directory": "Config"
    }
  }
}

agile_config 配置项说明
基于.net core 开发的轻量级配置中心 - AgileConfig_第7张图片

  • 修改 Program.cs 文件,在 Program.cs 设置使用 AgileConfig,如此增加环境后,AgileConfigProvider便会从相应环境 appsettings.json 中读取上述配置
  1. 在 appsettings.json 文件(默认根文件)配置 agileconfig 的配置信息。
 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseAgileConfig(e => Console.WriteLine($"configs {e.Action}"))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
  1. 使用 UseAgileConfig 扩展方法设置一个配置源。
public static IHostBuilder CreateHostBuilder(string[] args) =>
               Host.CreateDefaultBuilder(args)
               .UseAgileConfig(new ConfigClient($"Config\\appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json"), e => Console.WriteLine($"Action={e.Action},Key={e.Key}"))
               .ConfigureWebHostDefaults(webBuilder =>
               {
                  webBuilder.UseStartup<Startup>();
               });
  1. 使用 ConfigureAppConfiguration 扩展方法设置一个配置源。
public static IHostBuilder CreateHostBuilder(string[] args) => 
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.Sources.Clear();

                // 获取宿主机环境变量
                var env = hostingContext.HostingEnvironment;
                //Console.WriteLine($"HostingEnvironment:ApplicationName={env.ApplicationName},EnvironmentName={env.EnvironmentName},ContentRootPath={env.ContentRootPath}");

                //string basePath = Path.Join(AppContext.BaseDirectory, "Config");
                //string basePath = Path.Join(Directory.GetCurrentDirectory(), "Config");
                string basePath = Path.Join(env.ContentRootPath, "Config");

                // 设置 json 配置文件路径
                config.SetBasePath(basePath: basePath)
                        .AddJsonFile(path: "appsettings.json", optional: false, reloadOnChange: true)
                        .AddJsonFile(path: $"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

                if (args != null)
                {
                    config.AddCommandLine(args);
                }

                string configClientPath = string.Empty;
                if (env.IsProduction())
                {
                    configClientPath = $"{basePath}\\appsettings.json";
                }
                else
                {
                    // 指定参数获取环境变量名称,等效于 env.EnvironmentName
                    var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                    configClientPath = $"{basePath}\\appsettings.{environmentName}.json";
                }

                // new一个client实例,传参指定本地 appsettings.json 文件路径读取配置
                var configClient = new ConfigClient(configClientPath);
                // 使用 AddAgileConfig 配置一个新的 IConfigurationSource 注册项,并输出修改事件信息
                config.AddAgileConfig(configClient, e => Console.WriteLine($"Action={e.Action},Key={e.Key}"));
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

注意上面的2、3两种扩展方法是等效的,UseAgileConfig 扩展方法内部会设置 basePath 。

  • 在 Startup.cs 中添加服务
services.AddAgileConfig();

从 AgileConfig 配置中心读取客户端项目配置信息

AgileConfig 支持以下方式读取配置信息:

  • 支持 asp.net core 标准的 IConfiguration
  • IOptions 模式读取配置
  • AgileConfigClient 实例直接读取
  • IConfigClient 模式读取配置

新建 HomeController 文件,此处以为 IConfiguration,IConfigClient 为例,编写如下代码:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace WebApplication.AgileConfig.Controllers;

[Route("api/[controller]")]
[ApiController]
public class HomeController : ControllerBase
{
    private readonly ILogger<HomeController> _logger;
    private readonly IConfiguration _configuration;
    private readonly IConfigClient _configClient;
    
    public HomeController(ILogger<HomeController> logger, IConfiguration configuration, IConfigClient _configClient)
    {
        _logger = logger;
        _configuration = configuration;
        _configClient = configClient;
    }

    /// 
    /// 使用 IConfiguration 读取配置
    /// 
    /// 
    [HttpGet(ByIConfiguration)]
    public IActionResult ByIConfiguration()
    {
        string aaa = _configuration["Abc:aaa"];
        string info = $"Abc.aaa={aaa}";
        _logger.LogInformation(info);
        return Ok(info);
    }

    /// 
    /// 使用 IConfigClient 读取配置
    /// 
    /// 
    [HttpGet("ByIConfigClient")]
    public IActionResult ByIConfigClient()
    {
        var aaa = _configClient["Abc:aaa"];
        string info = $"Abc.aaa={aaa}";
        _logger.LogInformation(info);
        foreach (var item in _configClient.Data)
        {
            Console.WriteLine($"{item.Key} = {item.Value}");
        }
        return Ok(info);
    }
}

到此处客户端测试程序已经准备就绪,接下来在 AgileConfig 管理页面【应用】添加相关配置信息。

AgileConfig 配置中心读取配置的优先级

如果在 AgileConfig 中有则默认从那取值,没有再去找机密文件,再去找 appsettings.{env}.json,最后 appsettings.json,注意优先级最高的还是环境变量和命令行的配置。

  • https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#default-configuration
  • https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0#default-configuration

AgileConfig 配置中心添加客户端项目配置信息

选择 AgileConfig 管理页面 =》【应用】,新建客户端应用的配置信息,注意和上面的 appsettings.json 文件里面的配置保持一致。如下所示:
基于.net core 开发的轻量级配置中心 - AgileConfig_第8张图片
点击【配置项】=》【新建】按钮,即可添加配置信息。
基于.net core 开发的轻量级配置中心 - AgileConfig_第9张图片
从上图中可以看到, AgileConfig 配置中心默认提供4个环境变量:DEV、TEST、STAGING、PROD,可以新增 key-value 键值对、json 结构数据和 text 文本信息配置。

新建配置信息
基于.net core 开发的轻量级配置中心 - AgileConfig_第10张图片
新建配置信息后,页面显示如下:
基于.net core 开发的轻量级配置中心 - AgileConfig_第11张图片
点击【发布】即可让新增的配置信息生效。
基于.net core 开发的轻量级配置中心 - AgileConfig_第12张图片

项目测试

dotnet cli 启动项目

使用 dotnet cli 启动 WebApplication.AgileConfig 项目,输出如下信息:

Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\sws-dev-server\Desktop\dapr-demo\dapr-demo\WebApplication.AgileConfig> dotnet run

欢迎使用 .NET 6.0!
---------------------
SDK 版本: 6.0.300

遥测
---------
.NET 工具会收集用法数据,帮助我们改善你的体验。它由 Microsoft 收集并与社区共享。你可通过使用喜欢的 shell 将 DOTNET_CLI_TELEMETRY_OPTOUT 环境变量设置为 "1""true" 来选择退出遥测。

阅读有关 .NET CLI 工具遥测的更多信息: https://aka.ms/dotnet-cli-telemetry

----------------
已安装 ASP.NET Core HTTPS 开发证书。
若要信任该证书,请运行 "dotnet dev-certs https --trust" (仅限 Windows 和 macOS)。
了解 HTTPS: https://aka.ms/dotnet-https
----------------
编写你的第一个应用: https://aka.ms/dotnet-hello-world
查找新增功能: https://aka.ms/dotnet-whats-new
浏览文档: https://aka.ms/dotnet-docs
在 GitHub 上报告问题和查找源: https://github.com/dotnet/core
使用 "dotnet --help" 查看可用命令或访问: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
正在生成...
trce: AgileConfig.Client.ConfigClient[0]
      client try connect to server ws://192.168.10.251:15001/ws?client_name=client_name&client_tag=tag1
trce: AgileConfig.Client.ConfigClient[0]
      client connect server ws://192.168.10.251:15001/ws?client_name=client_name&client_tag=tag1 successful .
trce: AgileConfig.Client.ConfigClient[0]
      client load all the configs success by API: http://192.168.10.251:15002/api/config/app/chait?env=DEV , try count: 0.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Users\sws-dev-server\Desktop\dapr-demo\dapr-demo\WebApplication.AgileConfig

查看【节点】信息

浏览器查看【节点】信息,如下所示:

  • 输入 http://localhost:15000/ui#/node

基于.net core 开发的轻量级配置中心 - AgileConfig_第13张图片

API 接口获取配置信息

  • 访问 HomeController 获取配置信息

基于.net core 开发的轻量级配置中心 - AgileConfig_第14张图片
以上就是在 asp.net core webapi 项目中使用 AgileConfig 配置中心的全部过程,欢迎更多的小伙伴使用,基于 .net core 开发的轻量级配置中心,方便好用!

参考资料

  • https://github.com/dotnetcore/AgileConfig
  • https://hub.docker.com/r/kklldog/agile_config
  • https://www.cnblogs.com/kklldog/p/agile-config.html

你可能感兴趣的:(.NET,Core,跨平台,.netcore,docker,容器,轻量级配置中心,AgileConfig)