go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时])
go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时])
本节看看kratos的配置中心paladin(骑士)。
kratos对配置文件进行了梳理,配置管理模块化,如redis有redis的单独配置文件、bm有bm的单独配置文件,及为方便易用。
paladin 本质是一个config SDK客户端,包括了remote、file、mock几个抽象功能,方便使用本地文件或者远程配置中心,并且集成了对象自动reload功能。
现在看看paladin的几种配置方式 :
静态配置
照常 new 一个demo项目.
kratos new paladin
随便找个配置,看目录结构都知道http.toml在configs下,可以直接用名字get到,应该是kratos工具做了封装。
http.toml
[Server]
addr = "0.0.0.0:8000"
timeout = "1s"
// New new a bm server.
func New(s pb.DemoServer) (engine *bm.Engine, err error) {
var (
cfg bm.ServerConfig
ct paladin.TOML
)
if err = paladin.Get("http.toml").Unmarshal(&ct); err != nil {
return
}
if err = ct.Get("Server").UnmarshalTOML(&cfg); err != nil {
return
}
Get() 取到的是个Value结构,利用了encoding包(encoding包定义了供其它包使用的可以将数据在字节水平和文本表示之间转换的接口)做抽象接口。
// Value is config value, maybe a json/toml/ini/string file.
type Value struct {
val interface{}
slice interface{}
raw string
}
// Unmarshal is the interface implemented by an object that can unmarshal a textual representation of itself.
func (v *Value) Unmarshal(un encoding.TextUnmarshaler) error {
text, err := v.Raw()
if err != nil {
return err
}
return un.UnmarshalText([]byte(text))
}
// UnmarshalTOML unmarhsal toml to struct.
func (v *Value) UnmarshalTOML(dst interface{}) error {
text, err := v.Raw()
if err != nil {
return err
}
return toml.Unmarshal([]byte(text), dst)
}
直接kratos run的话,默认是读取的configs下的本地文件。 kratos/tool/run.go 里面是可以找到的.
package main
import (
"os"
"os/exec"
"path"
"path/filepath"
"github.com/urfave/cli"
)
func runAction(c *cli.Context) error {
base, err := os.Getwd()
if err != nil {
panic(err)
}
dir := buildDir(base, "cmd", 5)
conf := path.Join(filepath.Dir(dir), "configs")
args := append([]string{"run", "main.go", "-conf", conf}, c.Args()...)
cmd := exec.Command("go", args...)
cmd.Dir = dir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
return nil
}
flag注入
如果我们进行了build
I:\VSProject\kratos-note\paladin\paladin>cd cmd
I:\VSProject\kratos-note\paladin\paladin\cmd>kratos build
directory: I:\VSProject\kratos-note\paladin\paladin/cmd
kratos: 0.3.1
build success.
I:\VSProject\kratos-note\paladin\paladin\cmd>cmd.exe
INFO 12/30-22:25:07.054 I:/VSProject/kratos-note/paladin/paladin/cmd/main.go:19 paladin start
panic: lack of remote config center args
goroutine 1 [running]:
github.com/bilibili/kratos/pkg/conf/paladin.Init(0x0, 0x0, 0x0, 0x0, 0x0)
I:/VSProject/go/pkg/mod/github.com/bilibili/kratos@v0.3.2-0.20191224125553-6e1180f53a8e/pkg/conf/paladin/default.go:32 +0x25f
main.main()
I:/VSProject/kratos-note/paladin/paladin/cmd/main.go:20 +0x103
I:\VSProject\kratos-note\paladin\paladin\cmd>
会发现直接运行时跑不起来的,因为这时候找不到配置文件,因为这时候我们没有调用kratos run,paladin找不到配置目录。
实际paladin里面会有一个confPath变量,主函数做paladin.init()的时候会做flag注入。也方便了开发环境开发人员自行做配置修改。
package paladin
import (
"context"
"errors"
"flag"
)
var (
// DefaultClient default client.
DefaultClient Client
confPath string
)
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init config client.
// If confPath is set, it inits file client by default
// Otherwise we could pass args to init remote client
// args[0]: driver name, string type
func Init(args ...interface{}) (err error) {
if confPath != "" {
DefaultClient, err = NewFile(confPath)
} else {
var (
driver Driver
)
......
I:\VSProject\kratos-note\paladin\paladin\cmd>cmd.exe -conf=I:\VSProject\kratos-note\paladin\paladin\configs
INFO 12/30-22:41:43.717 I:/VSProject/kratos-note/paladin/paladin/cmd/main.go:19 paladin start
2019/12/30 22:41:43 start watch filepath: I:\VSProject\kratos-note\paladin\paladin\configs
INFO 12/30-22:41:43.781 I:/VSProject/go/pkg/mod/github.com/bilibili/kratos@v0.3.2-0.20191224125553-6e1180f53a8e/pkg/net/http/blademaster/server.go:98 blademaster: start http listen addr: 0.0.0.0:8000
[warden] config is Deprecated, argument will be ignored. please use -grpc flag or GRPC env to configure warden server.
INFO 12/30-22:41:43.790 I:/VSProject/go/pkg/mod/github.com/bilibili/kratos@v0.3.2-0.20191224125553-6e1180f53a8e/pkg/net/rpc/warden/server.go:329 warden: start grpc listen addr: [::]:9000
在线热加载配置
在线读取、变更的配置信息,比如某个业务开关,实现配置reload实时更新。
// Map is config map, key(filename) -> value(file).
type Map struct {
values atomic.Value
}
paladin.Map 通过 atomic.Value 自动热加载
# service.go
type Service struct {
ac *paladin.Map
}
func New() *Service {
// paladin.Map 通过atomic.Value支持自动热加载
var ac = new(paladin.TOML)
if err := paladin.Watch("application.toml", ac); err != nil {
panic(err)
}
s := &Service{
ac: ac,
}
return s
}
func (s *Service) Test() {
sw, err := s.ac.Get("switch").Bool()
if err != nil {
// TODO
}
// or use default value
sw := paladin.Bool(s.ac.Get("switch"), false)
}
测试
测试一下自动热加载,可以看到demo里面已经有添加了application.toml的自动热加载了
if err := paladin.Watch("application.toml", ac); err != nil {
panic(err)
}
关于watch
可以看到watch里面有个协程在监视变动情况。
// Watch watch on a key. The configuration implements the setter interface, which is invoked when the configuration changes.
func Watch(key string, s Setter) error {
v := DefaultClient.Get(key)
str, err := v.Raw()
if err != nil {
return err
}
if err := s.Set(str); err != nil {
return err
}
go func() {
for event := range WatchEvent(context.Background(), key) {
s.Set(event.Value)
}
}()
return nil
}
我们写个get()接口,打印下app.toml的keys() 看看是否会热加载。
func (s *Service) Get(ctx context.Context, req *pb.Req) (reply *pb.Resp, err error) {
log.Info("app toml : (%v)", s.ac.Keys())
app.toml
# This is a TOML document. Boom~
demoExpire = "24h"
[app]
addr = ["127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"]

接着随便加个字段,再次调用get()可以看ttt到加了进来
# This is a TOML document. Boom~
demoExpire = "24h"
[app]
addr = ["127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"]
[ttt]
xixi = "haha"

远程配置中心
通过环境变量注入,例如:APP_ID/DEPLOY_ENV/ZONE/HOSTNAME,然后通过paladin实现远程配置中心SDK进行配合使用。
目前只可以看到这个步骤是在Init()的时候做的,paladin本质是个客户端包,在不知道服务端实现的情况下暂时没找到样例,有机会遇见再补上。
// Init init config client.
// If confPath is set, it inits file client by default
// Otherwise we could pass args to init remote client
// args[0]: driver name, string type
func Init(args ...interface{}) (err error) {
if confPath != "" {
DefaultClient, err = NewFile(confPath)
} else {
var (
driver Driver
)
argsLackErr := errors.New("lack of remote config center args")
if len(args) == 0 {
panic(argsLackErr.Error())
}
argsInvalidErr := errors.New("invalid remote config center args")
driverName, ok := args[0].(string)
if !ok {
panic(argsInvalidErr.Error())
}
driver, err = GetDriver(driverName)
if err != nil {
return
}
DefaultClient, err = driver.New()
}
if err != nil {
return
}
return
}
体感paladin使用舒适度还是挺不错的、
断剑重铸之日,骑士归来之时
go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时])的更多相关文章
- 《深入理解Spring Cloud与微服务构建》学习笔记(二十)~配置中心Spring Cloud Config
本例重新创建项目,构建一个空的mavan工程. 一.Config Server 从本地读取配置文件 新建一个moudle config_server ,pom添加依赖 <dependency ...
- # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)
目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...
- go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer)
目录 go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer) demo demo server demo client 池 dao service p2c ro ...
- go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用)
目录 go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用) warden direct demo-server gr ...
- go微服务框架kratos学习笔记八 (kratos的依赖注入)
目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...
- go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin)
目录 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin) zipkin使用demo 数据持久化 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin ...
- 微服务框架surging学习之路——序列化 (转载https://www.cnblogs.com/alangur/p/10407727.html)
微服务框架surging学习之路——序列化 1.对微服务的理解 之前看到在群里的朋友门都在讨论微服务,看到他们的讨论,我也有了一些自己的理解,所谓微服务就是系统里的每个服务都 可以自由组合.自由组 ...
- golang微服务框架go-micro 入门笔记2.4 go-micro service解读
本章节阐述go-micro 服务发现原理 go-micro架构 下图来自go-micro官方 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go- ...
- golang微服务框架go-micro 入门笔记2.3 micro工具之消息接收和发布
本章节阐述micro消息订阅和发布相关内容 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架go-mi ...
随机推荐
- ArcMap影像纠偏
客户给了一张PNG图,如下图,需要提取其中北极航线. 策略是ArcMap中先配准PNG,使之与底图较好重合.再新建线图层,描出航线.这种彩色丰富的图,很难用栅格转矢量的方式,故应用描边法. 一.配准P ...
- 【NS2】学习点滴
1 $ns duplex-link-op $n2 $n3 queuePos 0.5#此命令用于设置在NAM中显示的队列方向#经测试,发现: # queuePos 0.5表示包从上到下进入队列# que ...
- 3DMAX安装失败怎样卸载重新安装3DMAX,解决3DMAX安装失败的方法总结
技术帖:3DMAX没有按照正确方式卸载,导致3DMAX安装失败.楼主也查过网上关于如何解决3DMAX安装失败的一些文章,是说删除几个3DMAX文件和3DMAX软件注册表就可以解决3DMAX安装失败的问 ...
- python生成器和各种推导式
一. 生成器 本质就是迭代器. 一个一个的创建对象 创建生成器的方式: 1. 生成器函数 2. 通过生成器表达式来获取生成器 3. 类型转换(看不到) 二. 生成器函数 (重点) 生成器函数中包含 y ...
- WebLogic Server再曝高风险远程命令执行0day漏洞,阿里云WAF支持免费应急服务
6月11日,阿里云安全团队发现WebLogic CVE-2019-2725补丁绕过的0day漏洞,并第一时间上报Oracle官方, 6月12日获得Oracle官方确认.由于Oracle尚未发布官方补丁 ...
- @hdu - 6329@ Problem K. Transport Construction
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 n 个点,第 i 个点位于 (xi, yi). 在第 i ...
- @loj - 2496@ 「AHOI / HNOI2018」毒瘤
目录 @description@ @solution@ @accepted code@ @details@ @description@ 从前有一名毒瘤. 毒瘤最近发现了量产毒瘤题的奥秘.考虑如下类型的 ...
- Vue.js 第4章 组件与路由
组件 什么是组件:组件就是一些标签结构的封装,同时为这些结构添加需要的业务逻辑,设置你想要的样式 一个组件中一般可以设置:结构,功能和样式 为什么要使用组件: 使用方便 复用 组件的创建和使用 组件的 ...
- oracle函数 CONCAT(c1,c2)
[功能]连接两个字符串 [参数]c1,c2 字符型表达式 [返回]字符型 同:c1||c2 [示例] select concat('010-','88888888')||'转23' 高乾竞电话 fro ...
- ashx不能折叠代码,没有智能提示
visual studio 2013有时候会遇到这个问题.没安装任何第三方插件,创建的是web网站项目.ashx文件忽然就没有intelligent智能提示了. 可以试试: 关闭visual stud ...