github.com/zly-app/zapp@v1.3.3/config/readme.md (about)

     1  
     2  <!-- TOC -->
     3  
     4  - [配置说明](#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)
     5  - [配置加载方式](#%E9%85%8D%E7%BD%AE%E5%8A%A0%E8%BD%BD%E6%96%B9%E5%BC%8F)
     6      - [从文件加载配置](#%E4%BB%8E%E6%96%87%E4%BB%B6%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE)
     7          - [框架配置示例](#%E6%A1%86%E6%9E%B6%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B)
     8          - [插件配置示例](#%E6%8F%92%E4%BB%B6%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B)
     9          - [服务配置示例](#%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B)
    10          - [组件配置示例](#%E7%BB%84%E4%BB%B6%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B)
    11          - [其它配置](#%E5%85%B6%E5%AE%83%E9%85%8D%E7%BD%AE)
    12      - [从viper加载配置](#%E4%BB%8Eviper%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE)
    13      - [从配置结构体加载配置](#%E4%BB%8E%E9%85%8D%E7%BD%AE%E7%BB%93%E6%9E%84%E4%BD%93%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE)
    14      - [引用配置文件](#%E5%BC%95%E7%94%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6)
    15      - [从apollo配置中心加载配置](#%E4%BB%8Eapollo%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE)
    16          - [apollo配置中心命名空间和配置说明](#apollo%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E5%92%8C%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)
    17          - [在配置文件中设置从apollo配置中心加载](#%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E8%AE%BE%E7%BD%AE%E4%BB%8Eapollo%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E5%8A%A0%E8%BD%BD)
    18  - [配置观察](#%E9%85%8D%E7%BD%AE%E8%A7%82%E5%AF%9F)
    19      - [使用示例](#%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B)
    20      - [自动解析泛型结构示例-强烈推荐用法](#%E8%87%AA%E5%8A%A8%E8%A7%A3%E6%9E%90%E6%B3%9B%E5%9E%8B%E7%BB%93%E6%9E%84%E7%A4%BA%E4%BE%8B-%E5%BC%BA%E7%83%88%E6%8E%A8%E8%8D%90%E7%94%A8%E6%B3%95)
    21  
    22  <!-- /TOC -->
    23  ---
    24  
    25  # 配置说明
    26  
    27  我们不需要任何配置就能直接跑起来, 当然你也可以使用配置
    28  
    29  + 配置来源优先级: 命令行`-c`指定文件 > WithViper > WithConfig > WithFiles > WithApollo > 默认配置文件
    30  + 使用命令 `-t` 来测试你的任何来源的配置是否正确.
    31  + 任何来源的配置都会构建为 [viper](https://github.com/spf13/viper) 结构, 然后再反序列化为配置结构体 [core.Config](../core/config.go)
    32  
    33  # 配置加载方式
    34  
    35  ## 从文件加载配置
    36  
    37  + 一般使用yaml作为配置文件, 可以使用命令行 `-c` 手动指定配置文件, 如果有多个配置文件用英文逗号分隔
    38  + 也可以使用 `WithFiles` 在代码中指定配置文件
    39  + 多个配置文件如果存在同配置分片会智能合并
    40  + 如果下面的某个配置文件存在, 会按从上到下的优先级自动加载<b><font color='red'>一个</font></b>配置文件.
    41  
    42     ```
    43     ./configs/default.yaml
    44     ./configs/default.yml
    45     ./configs/default.toml
    46     ./configs/default.json
    47     ```
    48  
    49  通用配置写法如下, 某些特定写法根据`它`的文档为准
    50  
    51  + 插件配置的key为 `plugins.{pluginType}`, pluginType是插件注册的类型值.
    52  + 服务配置的key为 `services.{serviceType}`, serviceType是服务注册的类型值.
    53  + 组件配置的key为 `components.{componentType}.{componentName}`, componentType是初始化组件时指定的类型值, componentName是获取组件时传入的名字.
    54  
    55  ### 框架配置示例
    56  
    57  以下所有配置字段都是可选的
    58  
    59  ```yaml
    60  frame: # 框架配置
    61      debug: true # debug标志
    62      Name: '' # app名
    63      Env: '' # 环境名
    64      FreeMemoryInterval: 120000 # 主动清理内存间隔时间(毫秒), <= 0 表示禁用
    65      WaitServiceRunTime: 1000 # 默认等待服务启动阶段, 等待时间(毫秒), 如果时间到未收到服务启动成功信号则将服务标记为不稳定状态然后继续开始工作(我们总不能一直等着吧)
    66      ServiceUnstableObserveTime: 10000 # 默认服务不稳定观察时间, 等待时间(毫秒), 如果时间到仍未收到服务启动成功信号也将服务标记为启动成功
    67      Flags: [] # flag, 注意: flag是忽略大小写的, 示例 ['a', 'B', 'c']
    68      Labels: # 标签, 注意: 标签名是忽略大小写的
    69          #Foo: Bar
    70      Log: # 日志配置
    71          Level: 'debug' # 日志等级, debug, info, warn, error, dpanic, panic, fatal
    72          Json: false # 启用json编码器, 输出的每一行日志转为json格式
    73          WriteToStream: true # 输出到屏幕
    74          WriteToFile: false # 日志是否输出到文件
    75          Name: '' # 日志文件名, 末尾会自动附加 .log 后缀
    76          AppendPid: false # 是否在日志文件名后附加进程号
    77          Path: './log' # 默认日志存放路径
    78          FileMaxSize: 32 # 每个日志最大尺寸,单位M
    79          FileMaxBackupsNum: 3 # 日志文件最多保存多少个备份, 0表示永久
    80          FileMaxDurableTime: 7 # 文件最多保存多长时间,单位天, 0表示永久
    81          Compress: false # 是否压缩历史日志
    82          TimeFormat: '2006-01-02 15:04:05' # 时间显示格式
    83          Color: true # 是否打印彩色日志等级, 只有关闭json编码器才生效
    84          CapitalLevel: false # 是否大写日志等级
    85          DevelopmentMode: true # 开发者模式, 在开发者模式下日志记录器在写完DPanic消息后程序会感到恐慌
    86          ShowFileAndLinenum: true # 显示文件路径和行号
    87          ShowFileAndLinenumMinLevel: 'debug' # 最小显示文件路径和行号的等级. 推荐所有等级都打印代码行, 相对于能快速定位问题来说, 这点性能损耗无关紧要
    88          MillisDuration: true # 对zap.Duration转为毫秒
    89      PrintConfig: true # app初始时是否打印配置
    90  ```
    91  
    92  ### 插件配置示例
    93  ```yaml
    94  plugins: # 插件配置
    95      my_plugin: # 插件类型
    96          Foo: Bar # 示例, 不代表真实插件配置情况
    97  ```
    98  
    99  ### 服务配置示例
   100  ```yaml
   101  services: # 服务配置
   102      api: # 服务类型
   103          Bind: :8080 # 示例, 不代表真实插件配置情况
   104      grpc: # 服务类型
   105          Bind: :3000 # 示例, 不代表真实插件配置情况
   106  ```
   107  
   108  ### 组件配置示例
   109  
   110  ```yaml
   111  components: # 组件配置
   112      cache: # 组件类型
   113          cacheName1: # 组件名, 比如提供多个redis客户端连接不同的redis集群
   114              CacheDB: memory # 示例, 不代表真实插件配置情况
   115          cacheName2: # 组件名, 比如提供多个redis客户端连接不同的redis集群
   116              CacheDB: memory # 示例, 不代表真实插件配置情况
   117  ```
   118  
   119  ### 其它配置
   120  
   121  > 除了 frame / plugins / services / components 这几类, 还可以添加自定义配置, 然后使用 `Parse` 方法将配置读取到变量中
   122  
   123  ```yaml
   124  myconfig: #自定义分片名
   125      Foo: Bar # 示例, 不代表真实情况
   126  ```
   127  
   128  + 更多配置说明阅读源码 [core.Config](../core/config.go)
   129  
   130  ## 从viper加载配置
   131  
   132  > 使用 `WithViper` 设置 [viper](https://github.com/spf13/viper) 结构
   133  
   134  ## 从配置结构体加载配置
   135  
   136  > 使用 `WithConfig` 设置配置结构体 [core.Config](../core/config.go)
   137  
   138  ## 引用配置文件
   139  
   140  + 可以在配置中引用另一个配置文件, 允许使用相对路径, 它相对于程序运行时当前目录.
   141  + 被引用的配置文件中不能再添加引用了, 它不会被识别.
   142  + 引用的配置文件必须存在
   143  
   144  示例:
   145  
   146  ```yaml
   147  include:
   148      files: './1.toml,./2.toml'
   149  ```
   150  
   151  ## 从`apollo`配置中心加载配置
   152  
   153  > 使用 `WithApollo` 设置apollo来源和如何加载
   154  
   155  ### `apollo`配置中心命名空间和配置说明
   156  
   157  zapp会将命名空间的名称作为配置顶级key, 该命名空间的配置会作为二级key和其值.
   158  
   159  示例 apollo 配置数据:
   160  
   161   | 命名空间   | field | value          |
   162   | ---------- | ----- | -------------- |
   163   | namespace1 | key1  | value          |
   164   | namespace1 | key2  | {"foo": "bar"} |
   165  
   166  以上apollo配置数据会被解析为以下配置
   167  
   168  ```yaml
   169  namespace1:
   170    key1: 'value'
   171    key2: '{"foo": "bar"}'
   172  ```
   173  
   174  zapp会将 `applicaiont` 命名空间下的 `frame`,`components`,`plugins`,`services`配置作为配置顶级key, 并将其值按照指定格式解析后赋予其子集(默认是`yaml`格式解析, 需要在apollo配置中设为你需要的格式).
   175  
   176  示例 apollo 配置数据:
   177  
   178   | 命名空间    | field    | value                                     | 备注                   |
   179   | ----------- | -------- | ----------------------------------------- | ---------------------- |
   180   | application | frame    | {"debug": true, "log": {"level": "info"}} | 会按照指定格式解析其值 |
   181   | application | plugins  | {"myplugin": {"foo": "bar"}}              | 会按照指定格式解析其值 |
   182   | application | otherKey | {"debug": true, "log": {"level": "info"}} | 不会解析其值           |
   183  
   184  以上apollo配置数据会被解析为以下配置
   185  
   186  ```yaml
   187  frame:
   188    debug: true
   189    log:
   190      level: 'info'
   191  plugins:
   192    foo: 'bar'
   193  application:
   194    otherKey: '{"debug": true, "log": {"level": "info"}}'
   195  ```
   196  
   197  ### 在配置文件中设置从`apollo`配置中心加载
   198  
   199  > 文件中添加如下设置, 参考 [config.ApolloConfig](./apollo.go). 从apollo拉取的配置会和文件的配置智能合并, 以apollo配置优先
   200  
   201  最小配置
   202  
   203  ```yaml
   204  apollo:
   205      Address: "http://127.0.0.1:8080"
   206      AppId: "your-appid"
   207  ```
   208  
   209  完整配置
   210  
   211  ```yaml
   212  apollo:
   213      Address: "http://127.0.0.1:8080"
   214      AppId: "your-appid"
   215      AccessKey: ""                  # 验证key, 优先级高于基础认证
   216      AuthBasicUser: ""              # 基础认证用户名, 可用于nginx的基础认证扩展
   217      AuthBasicPassword: ""          # 基础认证密码
   218      Cluster: "default"             # 集群名, 默认default
   219      AlwaysLoadFromRemote: false    # 总是从远程获取, 在远程加载失败时不会从备份文件加载
   220      BackupFile: "./configs/backup.apollo" # 本地备份文件, 留空表示不使用备份
   221      ApplicationDataType: "yaml"    # application命名空间下key的值的数据类型, 支持yaml,yml,toml,json
   222      ApplicationParseKeys: []       # application命名空间下哪些key数据会被解析, 无论如何默认的key(frame/components/plugins/services)会被解析
   223      Namespaces: []                 # 其他自定义命名空间
   224      IgnoreNamespaceNotFound: false # 是否忽略命名空间不存在, 无论如何设置application命名空间必须存在
   225  ```
   226  
   227  # 配置观察
   228  
   229  拥有以下特性
   230  
   231  + <b>一行代码接入配置中心, 解放心智负担</b>
   232  + 自动监听配置变更, 每次获取时拿到的是最新的配置数据
   233  + 开始watch时会立即从远程获取一次数据, 如果失败会立即打印`Fatal`日志并退出程序(配置有问题程序不应该启动)
   234  
   235  ## 使用示例
   236  
   237  ```go
   238  package main
   239  
   240  import (
   241  	"go.uber.org/zap"
   242  
   243  	"github.com/zly-app/zapp"
   244  	"github.com/zly-app/zapp/plugin/apollo_provider"
   245  )
   246  
   247  // 可以在定义变量时初始化
   248  var MyConfigWatch = zapp.WatchConfigKey("group_name", "key_name")
   249  
   250  func main() {
   251  	app := zapp.NewApp("test",
   252  		// 使用apollo配置中心作为配置提供者并设置为默认的配置提供者
   253  		apollo_provider.WithPlugin(true),
   254  	)
   255  	defer app.Exit()
   256  
   257  	// 也可以在这里初始化
   258  	//MyConfigWatch = zapp.WatchConfigKey("group_name", "key_name")
   259  
   260  	// 获取原始数据
   261  	y1 := MyConfigWatch.GetString()
   262  	app.Info(y1) // 1
   263  
   264  	// 转为 int 值
   265  	y2 := MyConfigWatch.GetInt()
   266  	app.Info(y2) // 1
   267  
   268  	// 转为 boolean 值
   269  	y3 := MyConfigWatch.GetBool()
   270  	app.Info(y3) // true
   271  
   272  	// 检查复合预期
   273  	b1 := MyConfigWatch.Expect("1")
   274  	b2 := MyConfigWatch.Expect(1)
   275  	b3 := MyConfigWatch.Expect(true)
   276  	app.Info(b1, b2, b3) // true, true, true
   277  
   278  	// 添加回调函数
   279  	MyConfigWatch.AddCallback(func(first bool, oldData, newData []byte) {
   280  		app.Info("回调",
   281  			zap.Bool("first", first),
   282  			zap.String("oldData", string(oldData)),
   283  			zap.String("newData", string(newData)),
   284  		)
   285  	})
   286  
   287  	app.Run()
   288  }
   289  ```
   290  
   291  ## 自动解析泛型结构示例-`(强烈推荐用法)`
   292  
   293  通过 `config.WatchKeyStruct` 观察一个key数值变更, 拥有以下额外特性
   294  
   295  + 自动将配置数据作为指定格式解析到一个类型中, 通过`Get`能直接拿到想要的配置数据
   296  + 开始watch时会立即对数据结构进行解析, 如果失败会立即打印`Fatal`日志并退出程序(配置有问题程序不应该启动)
   297  + 当配置变更时如果解析失败会打印一个`Error`日志并忽略该配置变更(获取到的配置是上一次正确解析的配置数据)
   298  + 只有配置变更时才会解析数据, 并不是每次获取数据都解析一次
   299  
   300  ```go
   301  package main
   302  
   303  import (
   304  	"time"
   305  
   306  	"github.com/zly-app/zapp"
   307  	"github.com/zly-app/zapp/plugin/apollo_provider"
   308  )
   309  
   310  type MyConfig struct {
   311  	A int `json:"a"`
   312  }
   313  
   314  // 可以在定义变量时初始化
   315  var MyConfigWatch = zapp.WatchConfigJson[*MyConfig]("group_name", "generic_key")
   316  
   317  func main() {
   318  	app := zapp.NewApp("test",
   319  		// 使用apollo配置中心作为配置提供者并设置为默认的配置提供者
   320  		apollo_provider.WithPlugin(true),
   321  	)
   322  	defer app.Exit()
   323  
   324  	// 也可以在这里初始化
   325  	//MyConfigWatch = zapp.WatchConfigJson[*MyConfig]("group_name", "generic_key")
   326  
   327  	// 获取数据
   328  	for {
   329  		a := MyConfigWatch.Get()
   330  		app.Info("数据", a)
   331  		time.Sleep(time.Second)
   332  	}
   333  }
   334  ```
   335  
   336  [其它示例代码](./watch_example)
   337