我是靠谱客的博主 名字长了才好记,这篇文章主要介绍go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk),现在分享给大家,希望可以做个参考。

本节看看kratos的配置中心paladin(骑士)。
kratos对配置文件进行了梳理,配置管理模块化,如redis有redis的单独配置文件、bm有bm的单独配置文件,及为方便易用。

paladin 本质是一个config SDK客户端,包括了remote、file、mock几个抽象功能,方便使用本地文件或者远程配置中心,并且集成了对象自动reload功能。

现在看看paladin的几种配置方式 :

静态配置

照常 new 一个demo项目.

复制代码
1
2
kratos new paladin

随便找个配置,看目录结构都知道http.toml在configs下,可以直接用名字get到,应该是kratos工具做了封装。

http.toml

复制代码
1
2
3
4
[Server] addr = "0.0.0.0:8000" timeout = "1s"
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
// 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包定义了供其它包使用的可以将数据在字节水平和文本表示之间转换的接口)做抽象接口。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 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 里面是可以找到的.

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
I:VSProjectkratos-notepaladinpaladin>cd cmd I:VSProjectkratos-notepaladinpaladincmd>kratos build directory: I:VSProjectkratos-notepaladinpaladin/cmd kratos: 0.3.1 build success. I:VSProjectkratos-notepaladinpaladincmd>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:VSProjectkratos-notepaladinpaladincmd>

会发现直接运行时跑不起来的,因为这时候找不到配置文件,因为这时候我们没有调用kratos run,paladin找不到配置目录。

实际paladin里面会有一个confPath变量,主函数做paladin.init()的时候会做flag注入。也方便了开发环境开发人员自行做配置修改。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 ) ......
复制代码
1
2
3
4
5
6
7
I:VSProjectkratos-notepaladinpaladincmd>cmd.exe -conf=I:VSProjectkratos-notepaladinpaladinconfigs 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:VSProjectkratos-notepaladinpaladinconfigs 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实时更新。

复制代码
1
2
3
4
5
// Map is config map, key(filename) -> value(file). type Map struct { values atomic.Value }

paladin.Map 通过 atomic.Value 自动热加载

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 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的自动热加载了

复制代码
1
2
3
4
5
if err := paladin.Watch("application.toml", ac); err != nil { panic(err) }

关于watch

可以看到watch里面有个协程在监视变动情况。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 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() 看看是否会热加载。

复制代码
1
2
3
4
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

复制代码
1
2
3
4
5
6
# 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到加了进来

复制代码
1
2
3
4
5
6
7
8
9
# 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本质是个客户端包,在不知道服务端实现的情况下暂时没找到样例,有机会遇见再补上。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 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)的全部内容,更多相关go微服务框架kratos学习笔记五(kratos内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(1681)

评论列表共有 0 条评论

立即
投稿
返回
顶部