微型数据库配置中心
https://www.nuget.org/packages/xu.TinyDBConfigProvider
在开发、实施中,需要保存第三方接口appKey、jwt、redis、项目自定义的配置等配置信息。在项目实施时为了保证应用的可用性,同一个应用需要部署多台Web服务器实例。配置信息都保存到本地配置文件,管理较为麻烦,如果有一个配置项要修改的话,就要修改多个地方,且容易出现修改不一致、遗漏等问题,因此需要引入集中配置中心服务,各个应用统一从配置中心服务读取配置。
目前,有 ctrip apollo 、Nacos、spring-cloud-config 、disconf 等开源的配置中心可供使用,功能非常强大,需要单独部署维护配置中心服务器。但是我的应用并没有复杂到那种程度,为了避免增加太多运维的成本,尽量减少应用使用的服务的数量及运维人员操作难度。
此外,阿里云、腾讯云等云服务商也有对应的配置中心服务可以用,不用自己去部署维护,但是我所服务的行业多数情况是不允许连接公网,也不想让应用依赖于某个特定云服务商。
因此把配置信息保存到数据库中,用数据库来做配置中心服务,最符合要求。
为方便各个项目读取配置及管理,开发了自定义的ConfigurationProvider,名字叫 xu.TinyDBConfigProvider。
配置保存到数据库表中,管理简单;
支持Sqlserver、mysql、sqlite等关系数据库,理论上只要.NET能连上的数据库都支持;
支持配置的版本化管理;
支持符合.NET配置命名规则的多级配置的覆盖;
配置项的值类型丰富,支持简单的字符串、数字等类型,也支持json格式;
采用.Net Standard2.0开发,支持.NET Framework、.NET Core;
为项目安装Nuget包:
在数据库中创建一张表,默认的表名 "TinyDBConfig",支持自定义表名。表必须有Id、KeyName、KeyValue三个列,Id定义为整数、自动增长列,KeyName和KeyValue都定义为字符串类型列,长度根据系统配置数据的长度合理的分配,KeyName列配置项的名字,KeyValue列配置项的值。
允许具有相同KeyName的多行数据,其中Id值最大的一条的值生效。
KeyName的值遵循 .NET 中配置的 “多层级数据的扁平化”(微软文档 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0)。
以下都是合法的KeyName列的值:
api:Jwt:Audience
age
api:0
api:1
KeyValue列的值用来保存KeyName类对应的配置的值。KeyValue的值可以是普通的值,也可以是json对象、json数组。比如下面都是合法的KeyValue值:
["a","b","c1"]
{"logFilePath":"D:/wwwroot/logs","minLevel":"INFO","source":1,"appID":"2007","sign":"96B03FD39E284C1E8FD45E0FFE298293","apiUri":"http://xxxx"}
abc123
通过NuGet安装开发包:
Install-Package xu.TinyDBConfigProvider -Version 1.0.0
配置数据库的连接字符串
虽然说项目中其他配置都可以放到数据库中了,但是数据库本身的连接字符串依然需要单独配置。它既可以配置到本地配置文件中,也可以通过环境变量等其它方式配置。下面用配置到本地json文件举例。
打开项目的appsettings.json,增加如下节点:
"ConnectionStrings": {
"DefaultConnection": "Data Source=TinyDB.sqlite"
}
接下来在Program.cs里的CreateHostBuilder方法的webBuilder.UseStartup();之前增加如下代码:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Host.ConfigureAppConfiguration((hostCtx, configBuilder) =>
{
string connStr = builder.Configuration.GetConnectionString("DefaultConnection");
configBuilder.AddTinyDBConfiguration(() => new Microsoft.Data.Sqlite.SqliteConnection(connStr), reloadOnChange: true, reloadInterval: TimeSpan.FromSeconds(10));
});
builder.Services.Configure<LogConfig>(builder.Configuration.GetSection("log"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
4.读取配置
创建类LogConfig
public class LogConfig
{
public string? LogFilePath { get; set; }
public string? MinLevel { get; set; }
public int Source { get; set; }
public string? AppID { get; set; }
public string? Sign { get; set; }
public string? ApiUri { get; set; }
}
然后在Program.cs中增加如下代码:
builder.Services.Configure<LogConfig>(builder.Configuration.GetSection("log"));
在Controller中读取配置:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IOptionsSnapshot<LogConfig> _logConfig;
public WeatherForecastController(IConfiguration configuration, IOptionsSnapshot<LogConfig> logConfig)
{
_configuration = configuration;
_logConfig = logConfig;
}
[HttpGet(Name = "GetWeatherForecast")]
public IActionResult Get()
{
var a = _configuration.GetSection("AllowedHosts").Value;
var b = _configuration.GetSection("Logging:LogLevel:Default").Value;
var c = _configuration.GetSection("Logging:LogLevel:Microsoft.AspNetCore").Value;
var d = _logConfig.Value.ApiUri;
var e = System.Text.Json.JsonSerializer.Serialize(_logConfig.Value);
var f = _configuration.GetSection("log:logFilePath").Value;
var g = _configuration.GetSection("log").Value;
var h = _configuration.GetSection("log").Get<LogConfig>();
return Ok();
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。