предисловие
Будь то микросервис или монолитный сервис, чтение конфигурации является неотъемлемой частью.
В большинстве приложений большая часть конфигурации загружается статически, и иногда может потребоваться чтение конфигурации из нескольких источников, что усложняет чтение конфигурации. В Go-Micro очень просто читать конфигурацию динамически или из нескольких источников, единственная сложностьнет документальной поддержки.
Go-Micro поддерживает чтение из нескольких источников, включая аргументы командной строки, файлы (json, yaml), etcd, consul, k8s и т. д.
Основная идея
Существует четыре основных концепции модуля конфигурации Go-Micro, а именно источник, кодировщик, считыватель и конфигурация.
заИсточник, представляющий прочитанный источник конфигурации., такие как файлы, командные строки, консул и т. д. и т. д. Источники, официально поддерживаемые Go-Micro:
- cli: параметр командной строки
- env: чтение из переменных окружения
- консул: читать от консула
- etcd: чтение из etcd
- файл: чтение из файла
- флаг: читать из флагов
- память: чтение из памяти
В дополнение к официально поддерживаемым источникам есть несколько других, поддерживаемых сообществом Go-Micro:
- configmap: читать из configmap k8s
- grpc: чтение с сервера grpc
- URL: читать с URL
- runtimevar: чтение из переменной времени выполнения Go Cloud Development Kit
- хранилище: чтение с сервера хранилища
заКодировщик, который представляет, как анализировать конфигурацию, например, файл json и файл yaml принадлежат одному и тому же источнику файлов, но используемые парсеры разные. Парсер Go-Micro по умолчанию — json.В дополнение к парсеру json официально поддерживаемые парсеры включают yaml, toml, xml и hcl.
заЧитатель, его роль заключается в объединении конфигурации нескольких источников в один. Потому что для json, yaml или consul структура конфигурации похожа, и со временем Go-Micro преобразует ее вmap[string]interface{}
формируются и сливаются.
заКонфиг, который выступает своеобразным менеджеромОн отвечает за такие функции, как создание конфигурации, чтение конфигурации, синхронизация конфигурации и мониторинг конфигурации.
Настроить битву чтения
подготовка документов
# ./file/config.json
{
"hosts": {
"database": {
"address": "10.0.0.1",
"port": 3306
},
"cache": {
"address": "10.0.0.2",
"port": 6379
}
}
}
# ./file/config.yaml
hosts:
database:
address: 10.0.0.3
port: 3307
cache:
address: 10.0.0.4
port: 6378
Примечание. Структура двух файлов одинакова, но они отображаются в разных формах, а содержимое конфигурации отличается, главным образом, для удобства последующей демонстрации.
json читать
1. Метод 1: используйте LoadFile для чтения (по сути, инкапсуляция функции загрузки)
import (
"encoding/json"
"fmt"
"github.com/micro/go-micro/v2/config"
"github.com/micro/go-micro/v2/config/source/file"
)
func readJson() {
// 加载配置文件
err := config.LoadFile("./file/config.json")
if err != nil {
panic(err)
}
// data的格式是 map[string]interface{}
// data map[hosts:map[cache:map[address:10.0.0.2 port:6379] database:map[address:10.0.0.1 port:3306]]]
data := config.Map()
fmt.Println("data", data)
}
2. Способ 2: создайте новый источник файла и используйте «Загрузить», чтобы прочитать его.
func readJsonBySource() {
// 使用的是默认的配置实例:DefaultConfig
fileSource := file.NewSource(file.WithPath("./file/config.json"))
err := config.Load(fileSource)
if err != nil {
panic(err)
}
data := config.Map()
fmt.Println("data", data)
}
3. Способ 3. Создайте новый экземпляр конфигурации и используйте «Загрузить», чтобы прочитать его.
func readJsonByCustom() {
// 自定义的配置实例
myConf, err := config.NewConfig()
if err != nil {
panic(err)
}
err = myConf.Load(file.NewSource(file.WithPath("./file/config.json")))
if err != nil {
panic(err)
}
data := myConf.Map()
fmt.Println("data", data)
}
4. Метод 4: чтение конфигурации и преобразование данных в структуру
type Host struct {
Address string `json:"address"`
Port int `json:"port"`
}
type Config struct {
Hosts map[string]Host `json:"hosts"`
}
func readJsonByStruct() {
err := config.LoadFile("./file/config.json")
if err != nil {
panic(err)
}
conf := Config{}
// 注意传的是指针
err = config.Scan(&conf)
if err != nil {
panic(err)
}
fmt.Println("data", conf)
}
5. Метод 5: прочтите конфигурацию, получите двоичные данные и проанализируйте их самостоятельно (для этого метода требуется новый источник).
func readJsonByStruct2() {
// 新建一个源
fileSource := file.NewSource(file.WithPath("./file/config.json"))
err := config.Load(fileSource)
if err != nil {
panic(err)
}
// 官方文档中提到,从source读取配置后会以 changeSet 的格式返回
changeSet, err := fileSource.Read()
if err != nil {
panic(err)
}
conf := Config{}
// 自己解析二进制数据
err = json.Unmarshal(changeSet.Data, &conf)
if err != nil {
panic(err)
}
fmt.Println("data", conf)
}
Всего для анализа json используется пять методов. Для других источников данных процесс аналогичен. Общий процесс таков:
- 1. Создайте новый источник, например file.NewSource, и передайте соответствующую конфигурацию, например путь к файлу и т. д.
- 2. Прочитайте данные в источнике, используйте
config.Load
метод, данные будут храниться в экземпляре конфигурации по умолчанию - 3. Для чтения данных из экземпляра конфигурации есть методы Map(), Read(), Scan() и другие на выбор.
ЯМЛ читать
Чтение yaml на самом деле похоже на json, с той лишь разницей, что парсер yaml должен быть определен, иначе парсер парсером json обязательно сообщит об ошибке.
import (
"fmt"
"github.com/micro/go-micro/v2/config"
"github.com/micro/go-micro/v2/config/encoder/yaml"
"github.com/micro/go-micro/v2/config/source"
"github.com/micro/go-micro/v2/config/source/file"
)
func readFromYaml() {
// 定义yaml解析器
enc := yaml.NewEncoder()
fileSource := file.NewSource(file.WithPath("./file/config.yaml"), source.WithEncoder(enc))
err := config.Load(fileSource)
if err != nil {
panic(err)
}
fmt.Println("data", config.Map())
}
Чтение из нескольких источников данных
Как упоминалось ранее, на самом деле есть небольшая разница между конфигурацией json и конфигурацией yaml, например номер порта и т. д., цель — продемонстрировать сценарий чтения Go-Micro из нескольких источников данных.
Так как это чтение из нескольких источников данных, есть приоритеты, и конфигурация с более высоким приоритетом переопределит конфигурацию с более низким приоритетом.Это также общий метод для большинства приложений.Сначала есть базовая конфигурация, а затем конфигурация постоянно обновляется. .
import (
"fmt"
"github.com/micro/go-micro/v2/config"
"github.com/micro/go-micro/v2/config/encoder/yaml"
"github.com/micro/go-micro/v2/config/source"
"github.com/micro/go-micro/v2/config/source/file"
)
func main() {
jsonSource := file.NewSource(file.WithPath("./file/config.json"))
yamlEncoder := yaml.NewEncoder()
yamlSource := file.NewSource(file.WithPath("./file/config.yaml"), source.WithEncoder(yamlEncoder))
// 后面读取的优先级越高,所以yaml的配置会覆盖json的配置
err := config.Load(jsonSource, yamlSource)
if err != nil {
panic(err)
}
// data map[hosts:map[cache:map[address:10.0.0.4 port:6378] database:map[address:10.0.0.3 port:3307]]]
fmt.Println("data", config.Map())
}
читать
Установка и настройка etcd здесь описываться не будем.Чтобы иметь возможность читать данные, мы должны сначала записать какие-то данные в etcd
# /micro/etcd 是我们的key
$ etcdctl put /micro/etcd '{"hosts":{"database":{"address":"10.0.0.1","port":3306},"cache":{"address":"10.0.0.2","port":6379}}}'
Читайте с Go-Micro:
package main
import (
"fmt"
"github.com/micro/go-micro/v2/config"
"github.com/micro/go-micro/v2/config/source/etcd"
)
func main() {
etcdSource := etcd.NewSource(
etcd.WithAddress("127.0.0.1:2379"),
etcd.WithPrefix("/micro/etcd"),
etcd.StripPrefix(true),
)
err := config.Load(etcdSource)
if err != nil {
panic(err)
}
conf := Config{}
err = config.Scan(&conf)
fmt.Println("data", conf)
}
Вы можете обнаружить, что конфигурация etcd на самом деле читается так же, как и файл.Это также гениальная часть Go-Micro, которая упрощает метод чтения различных источников данных с помощью высоко абстрактного метода.
Кроме того, могут быть мелкие партнерыStripPrefix
Есть сомнения по поводу этой конфигурации, но вы должны понять это на следующем примере.
func main() {
etcdSource := etcd.NewSource(
etcd.WithAddress("127.0.0.1:2379"),
etcd.WithPrefix("/micro/etcd"),
etcd.StripPrefix(false),
)
err := config.Load(etcdSource)
if err != nil {
panic(err)
}
changeSet, err := etcdSource.Read()
if err != nil {
panic(err)
}
// StripPrefix 从语义上看是去掉前缀的意思,如果没有去掉前缀,则会保留micro、etcd这两个key
// {"micro":{"etcd":{"hosts":{"cache":{"address":"10.0.0.2","port":6379},"database":{"address":"10.0.0.1","port":3306}}}}}
fmt.Println(string(changeSet.Data))
conf := Config{}
// Get的作用相当于 conf["micro"]["etcd"]
// 所以 Get("micro", "etcd") 之后的数据为 {"hosts":{"cache":{"address":"10.0.0.2","port":6379},"database":{"address":"10.0.0.1","port":3306}}}
err = config.Get("micro", "etcd").Scan(&conf)
if err != nil {
panic(err)
}
fmt.Println("data", conf)
}
Суммировать
Вот и все введение модуля конфигурации Go-Micro, я надеюсь, что он может быть вам полезен.Кроме того, вот лишь некоторые моменты, которые я считаю более важными.Если вам нужны более сложные, вы можете обратиться к следующимофициальная документация