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 ...
随机推荐
- 巨蟒python全栈开发-第11阶段 ansible_project7
今日大纲 1.发布详情页面 2.前端页面获取分支信息 3.前端界面获取commit信息与tag信息 4.获取线上最新版本 5.发布之实现nginx下线 6.发布之实现server发布 7.前端页面按钮 ...
- mysql 中合并查询结果union用法 or、in与union all 的查询效率
mysql 中合并查询结果union用法 or.in与union all 的查询效率 (2016-05-09 11:18:23) 转载▼ 标签: mysql union or in 分类: mysql ...
- golang micro client 报错500 {"id":"go.micro.client","code":408,"detail":"call timeout: context deadline exceeded","status":"Request Timeout"}
go micro web端连接services时,第一次访问提示500(broken pipe),排查发现客户端请求services时返回 {"id":"go.micro ...
- 几种map的排序规则
前几天在做理事会成员的时候遇到这个问题,需要根据职务的顺序,放入对应的成员,再把成员名字按首字母拼音顺序排序后,返回给前台解析,之前一直用TreeMap来存放这个排过序的List集合,发现就算我最先循 ...
- MySQL数据库字符集和整理
MySQL数据库字符集和整理(2009-11-20 22:23:37) mysql数据库 it 其实这个表在MySQL数据库中通过phpMyAdmin就能看到,icech只是把表格整理了一下方便 ...
- php Restful设计
1.restful是基于资源的,面向资源架构风格(一个链接,一张图.一个文本等等) 2.restful的http协议 2.1 url: 2.1.1 port 服务端口,默认为80 2.1.2 path ...
- 2019-10-31-Resharper-去掉注释拼写
title author date CreateTime categories Resharper 去掉注释拼写 lindexi 2019-10-31 9:8:5 +0800 2018-09-04 1 ...
- 【u238】暴力摩托
Time Limit: 1 second Memory Limit: 64 MB [问题描述] 晚会上大家在玩一款"暴力摩托"的游戏,它拥有非常逼真的画面和音响效果! 当然了,车子 ...
- BZOJ 4236 "JOIOJI"(前缀和+map+pair)
传送门: [1]:BZOJ [2]:洛谷 •题解 定义数组 a,b,c 分别表示 'J' , 'O' , 'I' 的前缀和: 要想使区间 (L,R] 满足条件当且仅当 a[R]-a[L] = b[R] ...
- P1097 方程的整数解
题目描述 给定一个整数N,求方程 \(x^3-x^2-x=N\) 的整数解. 保证解的范围在 \([-100,100]\) 范围内. 输入格式 一行一个整数 \(N(-10^6<=N<=1 ...