Тщательно изучите статьи из серии etcd (7): API сервиса etcd gRPC

задняя часть etcd

0 Обзор альбома

etcd является важным базовым компонентом облачной архитектуры, которая инкубируется и размещается CNCF. etcd можно использовать не только для регистрации и обнаружения сервисов в микросервисах и кластерах Kubernetes, но и как промежуточное ПО для хранения ключей и значений.

"Понимание статей серии etcd" познакомит с etcd с точки зрения базовой функциональной практики etcd, интерфейса API, принципа реализации, анализа исходного кода и опыта преодоления ям в реализации. Ожидается, что статей будет около 20, автор будет обновлять каждую неделю, прошу обратить внимание.

1 Обзор API Etcd

В этой статье мы начнем знакомить с основным дизайном API etcd3, в основном для общих служб интерфейса API. Это очень полезно для понимания основной идеи etcd. Все API etcd3 определены в службе gRPC, которая классифицирует удаленные вызовы процедур (RPC), понятные серверу etcd.

2 службы gRPC

Каждый запрос API, отправляемый на сервер etcd, является вызовом удаленной процедуры gRPC. Определения интерфейса RPC в etcd3 подразделяются на службы в зависимости от функциональности.

Важные сервисы для обработки ключей etcd включают в себя:

  • KV, создавать, обновлять, получать и удалять пары ключ-значение.
  • Следите, следите за ключевыми изменениями.
  • Lease, примитив, который использует сообщения проверки активности клиента.
  • Lock и т. д. обеспечивают поддержку распределенных общих блокировок.
  • Выборы, которые раскрывают механизм выборов на стороне клиента.

2.1 Запросы и ответы

Все RPC в etcd3 имеют одинаковый формат. У каждого RPC есть имя функции, которая принимает NameRequest в качестве параметра и возвращает NameResponse в качестве ответа. Например, вот описание Range RPC:

service KV {
  Range(RangeRequest) returns (RangeResponse)
  ...
}

2.2 Заголовки ответов

Все ответы на API etcd имеют дополнительный заголовок ответа, который включает метаданные кластера для ответа:

message ResponseHeader {
  uint64 cluster_id = 1;
  uint64 member_id = 2;
  int64 revision = 3;
  uint64 raft_term = 4;
}
  • Cluster_ID — идентификатор кластера, создавшего ответ.
  • Member_ID — идентификатор участника, сгенерировавшего ответ.
  • Редакция — номер версии хранилища пар "ключ-значение" на момент создания ответа.
  • Raft_Term — термин Raft участника на момент создания ответа.

Служба приложений может использовать поля Cluster_ID и Member_ID, чтобы убедиться, что в данный момент она обменивается данными с нужным кластером или участником.

Службы приложений могут использовать поле номера версии, чтобы узнать номер последней версии для текущего хранилища пар "ключ-значение". Эта функция особенно полезна, когда приложение указывает исторические версии для запросов о ходе времени и хочет знать последнюю версию по запросу.

Службы Application Services могут использовать Raft_Term, чтобы определить, когда кластер завершил выборы нового лидера.

3 Служба пары "ключ-значение"

3.1 Определение услуги KV

Большинство запросов к etcd обычно представляют собой запросы типа ключ-значение. Служба KV обеспечивает поддержку операций ключ-значение. В файле rpc.proto служба KV определяется следующим образом:

//rpc.proto
service KV {
  rpc Range(RangeRequest) returns (RangeResponse) {}

  rpc Put(PutRequest) returns (PutResponse) {}

  rpc DeleteRange(DeleteRangeRequest) returns (DeleteRangeResponse) {}

  rpc Txn(TxnRequest) returns (TxnResponse) {}

  rpc Compact(CompactionRequest) returns (CompactionResponse) {}
}

Введение каждой функции выглядит следующим образом:

  • Диапазон, получить ключ в диапазоне из хранилища ключ-значение;
  • Put, устанавливает данный ключ в хранилище ключ-значение, запрос на размещение добавляет ревизию хранилища ключ-значение и генерирует событие в истории событий;
  • DeleteRange, удаляет заданный диапазон из хранилища "ключ-значение", удаляет запросы на добавление ревизии хранилища "ключ-значение" и генерирует событие удаления для каждого удаленного ключа в истории событий;
  • Txn обрабатывает несколько запросов в одной транзакции, запрос txn увеличивает версию хранилища ключей и значений и создает событие с одной и той же версией для каждого завершенного запроса. Не допускается многократное изменение одного и того же ключа в txn;
  • Компактный, сжимает историю событий в хранилище ключ-значение etcd. Хранилище ключей и значений должно регулярно уплотняться, иначе история событий будет расти бесконечно.

Ниже мы подробно разберем каждый метод интерфейса.

3.2 Диапазонный метод

Метод Range получает ключи в диапазоне из хранилища ключей и значений и определяется следующим образом:

rpc Range(RangeRequest) returns (RangeResponse) {}

Следует отметить, что не существует метода манипулирования одной клавишей, даже если вы хотите получить доступ к одной клавише, вам нужно использовать метод Range. Тело сообщения RangeRequest запроса выглядит следующим образом:

message RangeRequest {
  enum SortOrder {
    NONE = 0; // 默认,不排序
    ASCEND = 1; // 正序,低的值在前
    DESCEND = 2; // 倒序,高的值在前
  }
  enum SortTarget {
    KEY = 0;
    VERSION = 1;
    CREATE = 2;
    MOD = 3;
    VALUE = 4;
  }

  bytes key = 1;

  // range_end 是请求范围的上限[key, range_end)
  bytes range_end = 2;

  // 请求返回的key的数量限制
  int64 limit = 3;

  int64 revision = 4;

  // 指定返回结果的排序顺序
  SortOrder sort_order = 5;

  // 用于排序的键值字段
  SortTarget sort_target = 6;

  bool serializable = 7;

  // 设置仅返回key而不需要value
  bool keys_only = 8;

  // 设置仅仅返回范围内key的数量
  bool count_only = 9;
}

В определении структуры запроса выше следует отметить, что ключ является первым ключом диапазона. Если range_end не указан, запрос ищет только этот ключ. range_end представляет верхний предел запроса, если range_end равен '\0', диапазон включает все ключи, большие или равные ключу; если range_end на один бит длиннее заданного ключа, то запрос диапазона получает все ключи с префиксом (данный ключ); если и ключ, и диапазон_конца равны '\0', запрос диапазона возвращает все ключи. ревизия Ревизия была сделана на момент сохранения пары ключ-значение диапазона. Если ревизия меньше или равна нулю, область действия находится в последнем хранилище пар "ключ-значение". Возвращает ErrCompacted в качестве ответа, если ревизия была сжата. serializable устанавливает запрос диапазона для локального чтения с использованием сериализованного члена. Запросы диапазона по умолчанию линеаризованы.Линеаризованные запросы имеют большую задержку и меньшую пропускную способность, чем сериализованные запросы, но отражают текущую согласованность кластера. Для повышения производительности сериализованные запросы диапазона обрабатываются локально за счет потенциально грязных чтений без необходимости согласования с другими узлами в кластере.

Тело ответа RangeResponse определяется следующим образом:

message RangeResponse {
  ResponseHeader header = 1;

  // kvs是匹配范围请求的键值对列表
  // 当请求数量时是空的
  repeated mvccpb.KeyValue kvs = 2;

  // more代表在被请求的范围内是否还有更多的 key
  bool more = 3;

  // 被请求范围内 key 的数量
  int64 count = 4;
}

Заголовок — это общий заголовок ответа, упомянутый в предыдущей сводке. Тело сообщения mvcpb.KeyValue определяется следующим образом:

message KeyValue {
  // key 是 bytes 格式的 key。不容许 key 为空
  bytes key = 1;

  // create_revision 是这个 key 最后创建的修订版本
  int64 create_revision = 2;

  // mod_revision 是这个 key 最后修改的修订版本
  int64 mod_revision = 3;

  int64 version = 4;

  // value 是 key 持有的值,bytes 格式。
  bytes value = 5;

  int64 lease = 6;
}

version — это версия ключа. Удаление сбрасывает версию на 0, а любая модификация ключа повышает ее версию. арендный договор — это идентификатор аренды, прикрепленный к ключу. Ключ будет удален по истечении срока действия прилагаемой аренды. Если аренда равна 0, к ключу не привязана аренда.

3.3 Метод пут

Метод put, используемый для хранения данного ключа в базе данных. Метод Put увеличивает версию хранилища ключей и значений и создает событие в истории событий.

rpc Put(PutRequest) returns (PutResponse) {}

Тело сообщения запроса — PutRequest:

message PutRequest {
  // byte数组形式的key,用来放置到键值对存储
  bytes key = 1;

  // byte 数组形式的 value,在键值对存储中和 key 关联
  bytes value = 2;

  int64 lease = 3;

  bool prev_kv = 4;
}

аренда, идентификатор аренды, связанный с ключом в хранилище "ключ-значение", 0 означает отсутствие аренды. Если prev_kv установлен, etcd получает последнюю пару ключ-значение перед изменением. Предыдущая пара ключ-значение будет возвращена в ответе put.

Тело ответа PutResponse определяется следующим образом:

message PutResponse {
  ResponseHeader header = 1;

  mvccpb.KeyValue prev_kv = 2;
}

Заголовок представляет собой общий заголовок ответа. Если prev_kv в запросе установлен, он вернет предыдущую пару ключ-значение.

3.4 Метод DeleteRange

Метод DeleteRange удаляет указанный диапазон из хранилища ключей и значений. Запросы на удаление добавляют ревизии в хранилище ключей и значений и генерируют событие удаления в истории событий для каждого удаленного ключа.

rpc DeleteRange(DeleteRangeRequest) returns (DeleteRangeResponse)

Тело сообщения запроса DeleteRangeRequest определяется следующим образом:

message DeleteRangeRequest { 
  bytes key = 1;

  bytes range_end = 2;

  bool prev_kv = 3;
}

key представляет собой начало диапазона для удаления. range_end — это последний ключ диапазона [key, range_end) для удаления. Если range_end не задан, диапазон определяется как содержащий только ключевой параметр; если range_end равен '\0', диапазон включает все ключи, большие или равные ключу параметра. Если prev_kv установлен, etcd получает последнюю пару ключ-значение перед удалением. Предыдущая пара ключ-значение будет возвращена в ответе на удаление. Тело сообщения DeleteRangeResponse ответа определяется следующим образом:

message DeleteRangeResponse {
  ResponseHeader header = 1;

  // 被范围删除请求删除的key的数量
  int64 deleted = 2;

  repeated mvccpb.KeyValue prev_kvs = 3;
}

Если в запросе установлено prev_kv, будет возвращена предыдущая пара ключ-значение.

4 Резюме

В этой статье в основном представлена ​​служба KV, связанная с Etcd API, и содержимое, связанное с ответом на запрос gRPC. Понимание этого является важной предпосылкой для изучения вызовов Etcd RPC. В следующих статьях мы продолжим знакомить вас с этими важными службами и интерфейсами в etcd.

Подписывайтесь на свежие статьи, приглашаю обратить внимание на мой публичный номер

Рекомендуемое чтение

  1. Сравнение etcd с другими компонентами k-v, такими как Zookeeper и Consul
  2. Тщательно изучите серию статей etcd (1): первое знакомство с etcd
  3. Тщательно изучите серию статей etcd (2): различные положения установки etcd
  4. Тщательно изучите серию статей etcd (3): эксплуатация и обслуживание кластера etcd, развертывание.
  5. Тщательно изучите серию статей etcd (4): безопасность etcd
  6. Тщательно изучите серию статей etcd (5): использование etcdctl
  7. Тщательно изучите серию статей etcd (6): etcd core API v3

Ссылаться на

etcd docs