Чтение конфигурации Go-Micro json/yaml/etcd

Go

предисловие

Будь то микросервис или монолитный сервис, чтение конфигурации является неотъемлемой частью.

В большинстве приложений большая часть конфигурации загружается статически, и иногда может потребоваться чтение конфигурации из нескольких источников, что усложняет чтение конфигурации. В 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, я надеюсь, что он может быть вам полезен.Кроме того, вот лишь некоторые моменты, которые я считаю более важными.Если вам нужны более сложные, вы можете обратиться к следующимофициальная документация