go kratos源码及配置解析

目录
  • 相关类图
    • 流程解释
  • 代码案例

相关类图

项目启动时一般前置条件为解析配置文件, 我们看下这块是怎么设计的.

流程解释

  • config 实现 config Interface 接口, 初始化reader对象
  • 调用Load方法, 通过入口注入的不同文件源, 调用实现了source interface 对应的Load方法(以file举例子)
  • file 通过 Load 入口, 判断是目录还是文件, 执行对应的方法, 拿到文件内容返回
  • config 拿到file返回的内容, 交给reader去合并
  • reader 根据文件格式(yml) 转为 map[string]interface{} 结构, 并进行覆盖合并, 将结果存到对象变量上
  • reader 处理完成后, config调用 file watcher 进行文件变更监听, 启动协程监听

由此可见, config对象其实作为入口, 将数据生产交给file、env, 将数据加工解析交给 reader

代码案例

init 接收外部参数定义解析配置文件地址

func init() {
	flag.StringVar(&commonconf, "common", "./configs/local", "common config path, eg: -conf config.yaml")
	flag.StringVar(&flagconf, "conf", "./configs/local/api", "config path, eg: -conf config.yaml")
    flag.Parse()
}

使用config.New初始化文件配置

//初始化配置
//新增两个配置源, 文件格式 common and flagconf 路径
c := config.New(
    config.WithSource(
        file.NewSource(commonconf),
        file.NewSource(flagconf),
    ),
)
// 关闭watch相关的监听器
defer c.Close()
// 加载配置文件
if err := c.Load(); err != nil {
	panic(err)
}
//解析配置到bc结构上
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
    panic(err)
}

我们看下config.New的实现

// 初始化解析器, 关联reader对象, 数据交给由reader加工和存储
func New(opts ...Option) Config {
	o := options{
		decoder:  defaultDecoder,
		resolver: defaultResolver,
	}
	for _, opt := range opts {
		opt(&o)
	}
	return &config{
		opts:   o,
		reader: newReader(o),
	}
}

Options 有下面几个属性

type options struct {
	sources  []Source // 配置源, 由初始化负责传入的source配置源
	decoder  Decoder //  解析器
	resolver Resolver // 变量解析替换
}

执行 Load 配置加载

func (c *config) Load() error {
    // 因为我们在入口传入的是file对象, 所以执行src load的时候也是file对象的 load 方法
	for _, src := range c.opts.sources {
        // 获取文件内容(可能是一个目录, 会存在多个文件)
		kvs, err := src.Load()
		if err != nil {
			return err
		}
		for _, v := range kvs {
			log.Debugf("config loaded: %s format: %s", v.Key, v.Format)
		}
        // 合并配置key
		if err = c.reader.Merge(kvs...); err != nil {
			log.Errorf("failed to merge config source: %v", err)
			return err
		}
        // 调用file watch, 监听文件变化
		w, err := src.Watch()
		if err != nil {
			log.Errorf("failed to watch config source: %v", err)
			return err
		}
		c.watchers = append(c.watchers, w)
        // 异步监听文件变化(调用对应的watch对象)
		go c.watch(w)
	}
    // 解析内容中是否包含 ${APPID:default} 变量
    // 如果在配置文件中存在 APPID: xx 配置, 则进行替换
    // 否则使用default默认值
	if err := c.reader.Resolve(); err != nil {
		log.Errorf("failed to resolve config source: %v", err)
		return err
	}
	return nil
}

异步watch

func (c *config) watch(w Watcher) {
	for {
		kvs, err := w.Next()
		if err != nil {
			if errors.Is(err, context.Canceled) {
				log.Infof("watcher's ctx cancel : %v", err)
				return
			}
			time.Sleep(time.Second)
			log.Errorf("failed to watch next config: %v", err)
			continue
		}
    	// 处理逻辑忽略 .....
		c.cached.Range(func(key, value interface{}) bool {
			k := key.(string)
			v := value.(Value)
			if n, ok := c.reader.Value(k); ok && reflect.TypeOf(n.Load()) == reflect.TypeOf(v.Load()) && !reflect.DeepEqual(n.Load(), v.Load()) {
				v.Store(n.Load())
				if o, ok := c.observers.Load(k); ok {
					o.(Observer)(k, v)
				}
			}
			return true
		})
	}
}

Scan 将配置转换成结构体

var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
    panic(err)
}

以上就是go kratos源码及配置解析的详细内容,更多关于kratos源码配置的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go中的应用配置管理详解

    目录 问题 解决 命令行参数 系统环境变量 打包进二进制文件 配置热更新 开源的fsnotify (1)安装 (2)案例 使用viper开源库实现热更新 问题 Go语言在编译时不会将配置文件这类第三方文件打包进二进制文件中 它既受当前路径的影响,也会因所填写的不同而改变,并非是绝对可靠的 解决 命令行参数 在Go语言中,可以直接通过flag标准库来实现该功能.实现逻辑为,如果存在命令行参数,则优先使用命令行参数,否则使用配置文件中的配置参数. 如下: var ( port string runM

  • go学习笔记读取consul配置文件详解

    目录 新建yaml文件 读取远程配置 新建yaml文件 在上文我们的 go学习笔记:使用 consul 做服务发现和配置共享 这里我们单独来用viper实现读取consul的配置, 我习惯与用yaml格式, 所以 首先 新建yaml文件 store: book: - author: john price: 10 - author: ken price: 12 bicycle: color: red price: 19.95 读取远程配置 可以直接调用viper.AddRemoteProvider

  • Django静态文件配置request对象方法ORM操作讲解

    目录 django框架请求流程 静态文件及相关配置 请求方法 request对象方法 pycharm链接MySQL Django链接MySQL Django ORM ORM语法 ORM外键关联 django框架请求流程 静态文件及相关配置 ORM:对象关系映射 python 映射   数据库类      表 对象     记录对象.属性     字段对应的值'ORM的存在可以使不会MySQL的程序员 使用python的语法操作数据库' 1.先去model.py中编写模型类(相当于是在建表) cl

  • GoFrame gredis配置文件及配置方法对比

    目录 前言摘要 GoFrame gredis 配置文件(推荐) 使用示例: 打印结果 配置方法(高级) 使用示例: 总结 前言摘要 上一篇文章为大家介绍了 GoFrame gcache使用实践 | 缓存控制 淘汰策略 ,得到了大家积极的反馈. 后续几篇文章再接再厉,仍然为大家介绍GoFrame框架缓存相关的知识点,以及自己项目使用中的一些总结思考,GoFrame框架下文简称gf. GoFrame gredis goframe框架支持两种方式来管理redis配置和获取redis对象,一种是通过配置

  • Android Studio gradle配置packagingOptions打包so库重复

    目录 正文 pickFirst 匹配 doNotStrip 设置 merge 将匹配的文件都添加到APK中 exclude 过滤 正文 在安卓开发中,通常会使用到gradle来编译,在安卓项目的app目录下的build.gradle中是用来对编译进行配置的,packagingOptions 是其中的一个打包配置,常见的设置项有exclude.pickFirst.doNotStrip.merge. 在日常代码开发中,我们需要知其然,而知其所以然,本文章知识也是Android日常瘦身的的必备知识.

  • go使用consul实现服务发现及配置共享实现详解

    目录 使用consul四大特性 通过docker安装consul 实现代码 运行结果 使用consul四大特性 1. 服务发现:利用服务注册,服务发现功能来实现服务治理. 2. 健康检查:利用consul注册的检查检查函数或脚本来判断服务是否健康,若服务不存在则从注册中心移除该服务,减少故障服务请求. 3. k/v数据存储:存储kv数据,可以作为服务配置中心来使用. 4. 多数据中心:可以建立多个consul集群通过inter网络进行互联,进一步保证数据可用性. 通过docker安装consul

  • Go微服务项目配置文件的定义和读取示例详解

    目录 前言 场景 定义配置 配置文件 加载配置文件 实现原理 总结 项目地址 前言 我们在写应用时,基本都会用到配置文件,从各种 shell 到 nginx 等,都有自己的配置文件.虽然这没有太多难度,但是配置项一般相对比较繁杂,解析.校验也会比较麻烦.本文就给大家讲讲我们是怎么简化配置文件的定义和解析的. 场景 如果我们要写一个 Restful API 的服务,配置项大概有如下内容: Host,侦听的 IP,如果不填,默认用 0.0.0.0 Port,侦听的端口,必填,只能是数字,大于等于80

  • go kratos源码及配置解析

    目录 相关类图 流程解释 代码案例 相关类图 项目启动时一般前置条件为解析配置文件, 我们看下这块是怎么设计的. 流程解释 config 实现 config Interface 接口, 初始化reader对象 调用Load方法, 通过入口注入的不同文件源, 调用实现了source interface 对应的Load方法(以file举例子) file 通过 Load 入口, 判断是目录还是文件, 执行对应的方法, 拿到文件内容返回 config 拿到file返回的内容, 交给reader去合并 r

  • Spring Aware源码设计示例解析

    目录 1. Aware介绍 2. Aware类别 2.1 BeanClassLoaderAware 2.2 BeanFactoryAware 2.3 BeanNameAware 2.4 ApplicationContextAware 3. Aware的使用 4. Aware的作用 5. Aware的调用 1. Aware介绍 前一篇讲到了BeanPostProcessor的相关知识,我们知道BeanPostProcessor是对整个容器中的Bean做前置和后置增强处理.这样的实现方式限制了开发者

  • vue解析指令compile源码层面使用解析

    目录 概述 compile 测试代码 结果 延伸及重点讲解 1. 类数组对象 2. RegExp.$1 3. nodeType 概述 上篇文章我们已经介绍了Vue的响应式原理,并实现了对数据的监听,监听的目的是为了及时更新视图,所以这篇文章就来介绍下vue解析指令并初始化视图部分. compile 在Vue的构造函数中对根元素进行编译 class MVue { constructor (options) { // 保存options this.$options = options this.$d

  • Java CountDownLatch的源码硬核解析

    目录 前言 介绍和使用 例子 概述 实现思路 源码解析 类结构图 await() 实现原理 countDown()实现原理 前言 对于并发执行,Java中的CountDownLatch是一个重要的类,简单理解, CountDownLatch中count down是倒数的意思,latch则是“门闩”的含义.在数量倒数到0的时候,打开“门闩”, 一起走,否则都等待在“门闩”的地方. 为了更好的理解CountDownLatch这个类,本文通过例子和源码带领大家深入解析这个类的原理. 介绍和使用 例子

  • Python Django源码运行过程解析

    目录 一.Django运行顺序 1.启动 1.1 命令行启动(测试服务器) 2.监听 2.1 runserver(测试服务器) 3.中间件的执行 本文只算是本人片面之言(当然也会借鉴网络上公开资料),而且技术含量比较低,内容质量也一般,大家仅限参考即可 如果对本文看不太懂,请先阅读后面文章,等都差不多看完再回顾来看 一.Django运行顺序 WSGI会不断监听客户端发送来的请求 先经过中间件进行分析验证处理 然后经过url分发与验证 视图层进行处理 再经过中间件进行分析验证处理 返回响应内容 1

  • Java8 Comparator源码演示及解析

    在前面一篇Java Comparable和Comparator对比详解中,对于java中的排序方法进行比较和具体剖析,主要是针对 Comparator接口和 Comparable接口,无论是哪种方式,都需要实现这个接口,并且重写里面的 方法. Java8中对其进行了优化,直接调用Comparator类即可实现一些自定义的排序功能,比如按照某个字段升序,并且按照某个字段降序排列:还有如果出现null 的情况怎么处理等等.下面是针对常见的 基础数据类型的list 和 对象的集合 进行排序的演示. /

  • Idea导入eureka源码实现过程解析

    通过GitHub获取Eureka源码 进入git bash命令行,自己找个目录,用来存放eureka源码,然后在目录里面,执行git clone  https://github.com/Netflix/eureka.git,就可以了,这个是需要点时间的,稍微有点慢,你等一会儿好了. git clone https://github.com/Netflix/eureka.git 获取eureka项目依赖 然后在eureka目录中,直接双击gradlew.bat就可以,这个是人家给你提供的命令,直接

  • JDK源码之PriorityQueue解析

    一.优先队列的应用 优先队列在程序开发中屡见不鲜,比如操作系统在进行进程调度时一种可行的算法是使用优先队列,当一个新的进程被fork()出来后,首先将它放到队列的最后,而操作系统内部的Scheduler负责不断地从这个优先队列中取出优先级较高的进程执行:爬虫系统在执行时往往也需要从一个优先级队列中循环取出高优先级任务并进行抓取.可以想见,如果类似这样的任务不适用优先级进行划分的话,系统必会出现故障,例如操作系统中低优先级进程持续占用资源而高优先级进程始终在队列中等待.此外,优先队列在贪婪算法中也

  • android异步消息机制 源码层面彻底解析(1)

    Handler.Message.Loopler.MessageQueen 首先看一下我们平常使用Handler的一个最常见用法. Handler handler =new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); //这里进行一些UI操作等处理 } new Thread(new Runnable() { @Override public void run() {

  • Andorid jar库源码Bolts原理解析

    Bolts: 作用: 用于链式执行跨线程代码,且传递数据 栗子: 复制代码 Task.call(new Callable<Boolean>() { @Override public Boolean call() throws Exception { return true; } }, Task.UI_THREAD_EXECUTOR); Task.callInBackground(new Callable<Boolean>() { @Override public Boolean c

随机推荐