API Consul
Это перевод статьи "An introduction to Consul key/value store API in Golang".
К сожалению, статья совсем не такая подробная и интересная как хотелось бы. Реквестирую больше экшена в статьях про consul и другие полезные go-тулзовины.
Введение
Consul это инструмент для обнаружения сервисов(service discovery) и простое хранилище пар ключ-значение, которое удобно использовать для конфигурации. Большинство свой функциональности consul предоставляет как простое RESTful HTTP API. Это позволяет писать клиенты к этому API на самых различных языках. В этом посте мы рассмотрим как работать с Go пакетом для Consul API, в частности, c хранилищем пар ключ-значение(далее просто k/v).
Для запуска примеров из статьи вам нужен компилятор Go и установленный consul. После этого нужно установить пакет для работы с consul:
go get github.com/hashicorp/consul/api
Теперь мы можем его импортировать, указав(для удобства и читаемоcти) псевдоним consulapi
.
import (
consulapi "github.com/hashicorp/consul/api"
)
Экземпляр клиента
Для создания клиента нужно вызвать функцию NewClient
и передать ей объект Config как аргумент. Самый простой способ создать экземпляр Config
, это вызвать функцию DefaultConfig
и изменить необходимые атрибуты, например Address
, Scheme
, Datacenter
и т.д.
config := consulapi.DefaultConfig()
config.Address = "192.168.1.2:8500"
consul, err := consulapi.NewClient(config)
В примере выше, атрибут Address
изменен на локальный IP адрес и порт. Также, мы можем изменить некоторый атрибуты, указав правильные переменные окружения. Но не забывайте, что значения указанные в коде, более приоритетны чем значения заданные через переменные окружения.
Давайте рассмотрим, какие атрибуты в объекте Config
доступны.
Address
Это строка, в которой указан адрес consul сервера в формате HOST:PORT
, например "192.168.1.2:8500"
. Его можно указать через переменную окружения CONSUL_HTTP_ADDR
. Дефолтное значение атрибута 127.0.0.1:8500
и это будет работать для большинства наших примеров, если вы не надумаете изменить адрес consul сервера.
Scheme
Этот атрибут должен быть строкой, указывающей какая схема используется в URI consul сервера. Значение может быть http
or https
. Дефолтное значение http
. Для управления этим значением есть две булевые переменные окружения: CONSUL_HTTP_SSL
и CONSUL_HTTP_SSL_VERIFY
. Если установить CONSUL_HTTP_SSL
как true
, то будет использоваться https
схема, иначе http
. Если CONSUL_HTTP_SSL_VERIFY
установить false
, то не будет SSL верификации.
Datacenter
Определяет какой датацентр нужно использовать. Если атрибут не указан, то используется дефолтный датацентр.
HttpClient
Этот атрибут определяет какой клиент необходимо использовать. Если не указан, используется клиент по умолчанию.
HttpAuth
Этот атрибут должен быть указателем на структуру HttpBasicAuth
, в которой указаны значения Username
и Password
в виде строк для HTTP Basic Authentication. Например вот так:
config := consulapi.DefaultConfig()
config.HttpAuth = &consulapi.HttpBasicAuth{Username: "guest", Password: "secret"}
consul, err := consulapi.NewClient(config)
Также, значение HttpAuth
можно установить с помощью переменной окружения CONSUL_HTTP_AUTH
. В эту переменную нужно записать строку с указанием пользователя, пароля и двоеточием в качестве разделителя. Если указна строка без двоеточия, то это будет обрабатываться как указание пользователя с пустым паролем. Например:
export CONSUL_HTTP_AUTH=guest:secret
export CONSUL_HTTP_AUTH=guest
WaitTime
Этот параметр определяет, как долго можно блокировать Watch
. Если ничего не указанно, то используется дефолтное значение.
Token
Атрибут используется для задания в реквесте специального ACL токена, который будет использоваться вместо токена агента по умолчанию.
Используя методы Client
вы можете получить доступ к различным возможностям API consul'а. В рамках данной статьи, нас интересует работа c k/v хранилищем.
k/v хранилище
Чтобы получить объект, с помощь которого мы сможем работать с k/v хранилищем, нам нужно вызвать метод KV
у экземпляра клиента.
kv := consul.KV()
В нашем распоряжении есть множество методов для CRUD операций и работой с k/v хранилищем. Структура KVPair
используется для представления одной записи.
type KVPair struct {
Key string
CreateIndex uint64
ModifyIndex uint64
LockIndex uint64
Flags uint64
Value []byte
Session string
}
- Key это ключ, как правило с разделительными слешами. Например
sites/1/domain
. - CreateIndex это номер индекса, указывающий, когда ключ был создан.
- ModifyIndex это номер индекса, указывающий, когда ключ был изменен.
- LockIndex это номер индекса, указывающий, когда была взята блокировка этого ключа.
- Flag может использоваться в рамках приложения, туда можно записывать дополнительную информацию.
- Value это само значение в виде байт-массива с максимальным значением 512 килобайт.
- Session можно записывать после создания сессии.
Тип KVPairs
это ничто иное как список ссылок на объекты KVPair
:
type KVPairs []*KVPair
QueryMeta
содержит некоторую дополнительную информацию по выполненному запросу:
type QueryMeta struct {
// LastIndex. Это поле может использоваться аналогично
// WaitIndex для предотвращения блокировки запроса
LastIndex uint64
// Время последнего взаимодействия с лидером
// для данного сервера(обработавшего запрос)
LastContact time.Duration
// Известен ли лидер
KnownLeader bool
// Время выполнения запроса
RequestTime time.Duration
}
QueryOptions
используется для указания дополнительных параметров при запросе:
type QueryOptions struct {
// Обеспечивает перезаписывание датацетром DC
// DC, указанного в Config.
Datacenter string
// AllowStale позволяет любому серверу(кроме лидера) consult
// обрабатывать запросы на чтение. Это уменьшает задержки и
// увеличивает пропускную способность.
AllowStale bool
// RequireConsistent увеличивает достоверность данных,
// отдаваемых клиенту. Это дороже по производительности,
// но предотвращает отдачу старых данных клиенту.
RequireConsistent bool
// WaitIndex используется для блокирующих запросов.
// Ожидаем истечение таймаута или следующего
// доступного индекса.
WaitIndex uint64
// WaitTime используется для указания времени ожидания.
// По умолчанию берется значение из конфига,
// но мы можем его поменять.
WaitTime time.Duration
// Token используется для указания ACL в запросе,
// который перетирает дефолтный токен агента.
Token string
}
Put
Сигнатура метода выглядит так:
func (k *KV) Put(p *KVPair, q *WriteOptions) (*WriteMeta, error)
А вот так этим методом можно пользоваться:
d := &consulapi.KVPair{Key: "sites/1/domain", Value: []byte("example.com")}
kv.Acquire(d, nil)
Get
Сигнатура метода
func (k *KV) Get(key string, q *QueryOptions) (*KVPair, *QueryMeta, error)
И его использования:
kvp, qm, error := kv.Get("sites/1/domain", nil)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(string(kvp.Value))
}
Delete
Сигнатура метода Delete
:
func (k *KV) Delete(key string, w *WriteOptions) (*WriteMeta, error)
И пример как им пользоваться:
wm, err := kv.Delete("sites/1/domain", nil)
if err != nil {
fmt.Println(err)
}
Keys
Метод для получения списка ключей:
func (k *KV) Keys(prefix, separator string, q *QueryOptions) ([]string, *QueryMeta, error)
List
Получение пачки значений по префиксу ключа:
func (k *KV) List(prefix string, q *QueryOptions) (KVPairs, *QueryMeta, error)
DeleteTree
Метод для удаления набора ключей с одинаковым префиксом:
func (k *KV) DeleteTree(prefix string, w *WriteOptions) (*WriteMeta, error)
И пример использования:
wm, err := kv.DeleteTree("sites", nil)
if err != nil {
fmt.Println(err)
}
Набор примитивов для более сложных операций
Существует несколько примитивов для продвинутых операций, таких как комплексная синхронизация и выбор лидера. Перечислим несколько методов:
- Acquire используется для операций приобретения(acquisition). Можно применять к
Key
,Flags
,Value
иSession
. В случае удачи возвращает true, иначе false. - CAS используется для операций "проверить и установить"(Check-And-Set). Работает с
Key
,ModifyIndex
,Flags
иValue
. В случае удачи возвращает true, иначе false. - DeleteCAS эта операция аналогична CAS. Работает с
Key
иModifyIndex
. В случае удачи возвращает true, иначе false. - Release используется для лока релизной операции. Работает с
Key
,Flags
,Value
иSession
. В случае удачи возвращает true, иначе false.
Заключение
В этой статья мы рассмотрели API k/v хранилище consul'a и его использование в рамках пакета. У consul'a еще много других возможностей, кроме k/v хранилища. И очень круто, что пакет для работы API написан самими разработчиками consul.