[Stardust]星尘配置中心

在分布式系统开发中,配置中心必不可少。在中通几年时间里,为了配合大数据计算平台,统一管理数百个微小应用,设计了一套轻量级配置中心。星尘配置中心在其理念基础上改进,针对中小团队而全新设计!

源码:https://github.com/NewLifeX/Stardust

试用:http://star.newlifex.com

Nuget包:NewLife.Stardust、NewLife.Stardust.Extensions

快速预览

三个应用,配置数据如下:

基于标签的变量引用,是星尘配置中心的亮点,请求接口返回数据如下:

配置请求时加上作用域 scope=prod

不同作用域,返回了不同的配置值。prod域不存在,使用了_master的默认空域配置10.0.0.1。

功能特点

配置中心本质上就是一个名值字典,在开发实践中需要解决多环境、多团队协同等问题。

星尘配置中心主要功能特点如下:

  1. 使用简单,设置名值配置后,应用可通过接口获取配置,NewLife组件配置系统集成;

  2. 支持嵌套,${_teamName}即可从本应用或共享应用中获取_teamName进行替换,可以灵活构建各种配置项;

  3. 支持共享,Common应用共享给StarWeb,StarWeb可以直接返回Common的配置,或者作为替换变量,Common就是各团队统一使用的配置值,一次修改多个应用生效;

  4. 支持忽略,下划线开头的配置项仅作为变量,不会返回给客户端;

  5. 支持跨应用引用,StarWeb的conn_shop设置${_master@Db},指定引用Db应用的_master变量,而无需Db共享给StarWeb,只有DBA维护Db和Redis,而几乎所有应用都需要用到;

  6. 支持多作用域,Db有默认空域以及dev作用域的_master,以区分生产环境和开发环境的数据库配置,StarWeb应用使用时只管引用_master,dev作用域将穿透到所有被引用变量;

基本用法

使用 HttpConfigProvider 可以直接访问星尘配置中心,也可以访问阿波罗配置中心,具体参考

此处为语雀文档,点击链接查看:https://www.yuque.com/go/doc/31612474

示例代码:

var provider = new HttpConfigProvider
{
    Server = "http://star.newlifex.com:6600",
    //Server = "http://localhost:6600",
    AppId = "StarWeb"
};


var str = provider["test1"];
Assert.NotEmpty(str);


var keys = provider.Keys.ToArray();
Assert.NotNull(keys);


var model = provider.Load<Model2>();
Assert.NotNull(model);
Assert.NotEmpty(model.Test);
Assert.Equal(str, model.Test);
Assert.NotEmpty(model.Shop);
Assert.NotEmpty(model.Title);
Assert.Equal("NewLife开发团队", model.Title);


var model2 = new Model2();
provider.Bind(model2);
Assert.Equal(str, model2.Test);
Assert.NotEmpty(model.Shop);
Assert.Equal("NewLife开发团队", model.Title);


provider.LoadAll();

实例化HttpConfigProvider时,需要指定星尘服务端地址和应用AppId,还需要密钥Secret(如果服务端设置了应用密钥)。

得到provider以后,就可以直接访问配置数据了,例如 provider["test1"]。

也可以通过Load方法,把配置数据设置到一个对象的属性上去。

还可以通过Bind方法,把配置数据绑定到一个对象的属性上,这个办法还具备自动刷新功能,也就是说,服务器配置数据变化以后,HttpConfigProvider内部将会更新该对象的属性。这里的更新可能因为网络原因最多有一分钟的延迟。Bind的用法非常适用于配置对象。

集成用法

星尘配置中心的客户端集成在星尘组件包 NewLife.Stardust 中,直接从nuget引用。

实例化星尘工厂后,即可得到配置提供者对象:

var star = new StarFactory(null, "StarWeb", null);


services.AddSingleton(star);
services.AddSingleton(star.Tracer);
services.AddSingleton(star.Config);


// 数据库连接配置
DAL.GetConfig = star.Config.GetConfig;

这的star.Config,就是上面“基本用法”中的IConfigProvider,实际类型HttpConfigProvider。借助星尘工厂,统一了应用的身份验证。同时,这里不需要自己配置星尘服务端地址,它将会自动读取配置文件appsettings.json的StarServer配置项,或者跟服务器节点本机的StarAgent沟通得到。

DAL是数据中间件的数据层,GetConfig直接建立跟星尘配置中心的绑定关系,此举让XCode能够跟星尘紧密结合在一起。

这里把star.Config注入到ioc中,业务代码使用的时候,就可以通过IConfigProvider得到实际配置对象。

消费使用例子如下,JobHost解析使用了IConfigProvider,SyncOrder等作业类内部也可以解析使用。

using System;
using System.Threading;
using System.Threading.Tasks;
using AntJob;
using AntJob.Providers;
using NewLife;
using NewLife.Configuration;
using NewLife.Log;
using NewLife.Model;
using OrderCenter.Api.JobServices;


namespace OrderCenter.Tasks.JobServices
{
    public class JobHost : BackgroundService
    {
        private readonly IServiceProvider _provider;
        private readonly IConfigProvider _config;
        private readonly OrderStatService _stat;
        private Scheduler _scheduler;


        public JobHost(IServiceProvider provider, IConfigProvider config, OrderStatService service)
        {
            _provider = provider;
            _config = config;
            _stat = service;
        }


        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var set = AntSetting.Current;
            var services = ObjectContainer.Current;


            var server = _config["antServer"];
            if (!server.IsNullOrEmpty())
            {
                set.Server = server;
                set.Save();
            }


            // 实例化调度器
            var sc = new Scheduler
            {
                Tracer = DefaultTracer.Instance,


                // 使用分布式调度引擎替换默认的本地文件调度
                Provider = new NetworkJobProvider
                {
                    Server = set.Server,
                    AppID = set.AppID,
                    Secret = set.Secret,
                    Debug = false
                }
            };


            // 订单冷热同步。热表订单同步到冷表
            sc.AddHandler<SyncOrder>();
            sc.AddHandler<SyncOrder2>();


            // 启动调度引擎,调度器内部多线程处理
            sc.Start();
            _scheduler = sc;


            return Task.CompletedTask;
        }


        public override Task StopAsync(CancellationToken cancellationToken)
        {
            _scheduler.TryDispose();
            _scheduler = null;


            return Task.CompletedTask;
        }
    }
}

.NET Core 高度集成用法

在Asp.NET Core应用中,可以整体引入星尘全家桶,除了配置中心,还有监控中心、注册中心(服务注册与发现)、日志中心等。

只需要在Startup的ConfigureServices中使用一句:services.AddStardust("StarWeb")

这里不需要自己配置星尘服务端地址和密钥,它将会自动读取配置文件appsettings.json的StarServer配置项,或者跟服务器节点本机的StarAgent沟通得到。

using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NewLife.Cube;
using Stardust.Data;
using Stardust.Server.Services;
using XCode.DataAccessLayer;


namespace Stardust.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration) => Configuration = configuration;


        public IConfiguration Configuration { get; }


        public void ConfigureServices(IServiceCollection services)
        {
            var star = services.AddStardust("StarWeb");


            services.AddControllersWithViews();
            services.AddCube();
        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // 使用Cube前添加自己的管道
            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();
            else
                app.UseExceptionHandler("/CubeHome/Error");


            app.UseCube(env);


            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=CubeHome}/{action=Index}/{id?}");
            });


            // 发布服务到星尘注册中心,需要指定服务名
            app.RegisterService("StarWeb");
        }
    }
}

配置管理

应用引入NewLife.Stardust包接入星尘配置中心以后,配置中心将会自动创建应用(要求StarServer下的config/starserver.config的AutoRegister设置为true)。

应用配置

进入星尘StarWeb管理平台(例如http://star.newlifex.com/),配置中心子系统,应用配置页面,即可管理各个应用的配置数据。

每个应用的基本信息,包括:

    • 启用。是否禁止该应用使用配置中心;

    • 版本。该应用正在使用的配置版本号,客户端请求配置数据时,如果传入相同版本号,则认为配置没有改变,不返回任何配置数据,意为让客户端继续使用上一次的配置数据;

    • 下一版本。下一个未发布版本,该应用的配置数据有改变,但是还没有发布,此时下一版本号会比当前版本号要大,同时“发布”按钮显示出来;

    • 定时发布。设置定时发布下一个版本的时间,到期后自动发布下一版本;

    • 可被依赖。指定应用是否可以被其它应用依赖,例如项目组内部的工控配置,可以写到一起,设置为可被依赖,然后其它项目即可直接依赖该应用,从而得到该应用的全部配置数据,融入自有配置数据;

    • 依赖应用。当前应用依赖其它的应用;

    • 全局。全局应用意为该应用的配置数据融入所有其它应用的配置数据中,在其它应用拉取时一起返回;

管理配置

从应用配置找到应用,点击“配置”进入管理页面。

在这里可以添加配置数据,也可以修改维护配置。不用担心对线上系统造成影响,因为在发布修改之前,所做修改并不会被各个应用客户端拉取。

配置名称以下划线开头时,仅用于内嵌的变量引用,并不会返回给客户端。这是星尘配置中心的一个特色。

在星尘配置中心,某个应用之下,配置名称并不是唯一的,配置名称加上作用域Scope才是唯一。也就是说,同样一个配置中,不同的作用域可以有不同的值。作用域Scope常用于dev/test/prod/uat等环境区分。

如果某个配置数据作用域为空,表示该配置的默认值,当该配置名称没有任何作用域配置客户端请求时,使用空域配置数据。如果没有空域配置,客户端指定的配置域又找不到时,配置中心将会给客户端返回错误信息。

作用域不仅仅适用于某个应用,而是能够穿透到内嵌应用。因此,conn_shop配置值是${_master@Db};database=shop,引用了Db应用的_master,而Db里面配置了多个_master,分别对应不同的配置值。conn_shop得以在不同环境下使用不同的数据库连接字符串。

全局应用

每个公司可以指定一个应用作为全局应用,存放所有应用都需要使用的配置数据,例如CompanyName=新生命。各个应用就不再需要配置CompanyName,而应用端可以直接使用。

当然,系统并没有限制只能使用一个全局应用,设置多个全局应用也是可以的,只是可能带来管理上的麻烦。

演示系统中的Common就是全局应用,它内部的_teamName可被所有应用直接使用,而无需建立依赖关系。

需要注意的是,_teamName以下划线开头,表示内部配置,仅用于变量引用,不会作为配置数据返回给应用客户端。

同名配置优先级:应用内该Scope配置>应用内空域配置>依赖应用>全局应用

依赖应用

考虑到团队内部的公共应用需要,可以设置某个应用为团队内部的公共应用。团队内部各个应用可以直接引用该依赖引用。一个公司可能有多个开发团队,不同的团队有自己的公共应用。

演示系统中的Db就是可被依赖的应用,然后StarWeb应用依赖了该Db应用,多选。

因此StarWeb自动“获得”了Db的所有配置项,这里只有_master。

需要注意的是,_master以下划线开头,表示内部配置,仅用于变量引用,不会作为配置数据返回给应用客户端。

同名配置优先级:应用内该Scope配置>应用内空域配置>依赖应用>全局应用

变量引用

基于公共配置抽象的需要,星尘配置中心支持变量引用。允许一个配置数据引用其它配置内容。配置标签以美元符号和大括号组成,例如conn_shop的配置值${_master@Db};database=shop,表示引用Db应用的_master配置值,然后在后面加上一些自己的内容。

这里的例子跟依赖应用有点关系,如果建立了依赖引用,那么这里可以直接写${_master};database=shop。因此,依赖引用不是必须的,可以通过@Db的形式,强行引用任意其它应用的配置数据。但是强烈不建议这么做,因为这样子会让被引用者根本分不清楚自己被谁引用了,从而带来管理风险。

同名配置优先级:应用内该Scope配置>应用内空域配置>依赖应用>全局应用

版本发布

新增或者修改配置数据以后,配置数据版本号将会变成当前应用版本号加一,表示这是未发布新版本。

此时,在应用内部,或者外面列表页,点击“发布”,都将会把当前版本号改为下一版本号,通知客户端该应用的配置数据有改变。

作用域规则

配置客户端默认并不会向配置中心提交scope,而是由配置中心根据来源IP地址计算得到scope。

当IP满足某个匹配条件时,产生某个结果,scope等于指定值。

同步阿波罗配置

星尘配置中心支持从阿波罗同步指定应用同步配置数据。

阿波罗接入,并不需要密钥验证,所以……

总结

星尘配置中心客户端可以紧密结合星尘,通知紧密结合XCode数据中间件、魔方快速开发平台、蚂蚁调度系统、Redis消息队列等等NewLife系列产品组件。

同时,该客户端还可以对接阿波罗配置中心,使用方法不变。

星尘配置中心为了简化使用,提升用户体验,不再设置命名空间等概念。建议普通用户直接给各个应用设置配置数据即可,少数高级用户可以使用全局、依赖、引用等高级特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值