title |
---|
Клиент серверный протокол |
Для взаимодействия между клиентом и сервером используется клиент-серверный протокол, основанный на TCP. Используемые базовые структуры данных описаны в секции сетевого протокола.
В этой секции указаны основные случаи при работе с приложением: как установить соединение, выполнить команды и другие.
Подключение между клиентом и сервером инициирует клиент.
Алгоритм установления соединения:
- Клиент устанавливает подключение с сервером (сокет)
- Клиент отправляет Authorization Request пакет, в котором указывает способ аутентификации и необходимые для этого данные.
- Сервер авторизует клиента и отправляет Authorization Response пакет клиенту
- Иначе, если авторизация неуспешна:
- В ответном пакете указывается сообщение об ошибке
- Сервер закрывает соединение
- Конец
- Клиент отправляет Bootstrap Request пакет, в котором указывает версию приложения, с которой собирается работать
- Сервер проверяет совместимость указанной версии со своей и отправляет Bootstrap Response пакет
- Если версии не совместимы:
- В ответном пакете указывается сообщение об ошибке
- Сервер закрывает соединение
- Конец
- Сервер начинает обработку запросов пользователя
На данный момент, аутентификация не поддерживается. В пакетах Authorization* указывается пустой тип аутентификации.
sequenceDiagram
actor Клиент
participant Сервер
Клиент -> Сервер: Установка TCP соединения
Клиент ->> Сервер: Authorization Request
Сервер ->> Клиент: Authorization Response
Клиент ->> Сервер: Bootstrap Request
Сервер ->> Клиент: Bootstrap Response
Каждая команда бизнес-логики отправляется в отдельном пакете - CommandRequest. При успешном выполнении команды, сервер отправляет Command Response, в котором содержится результат. Если в процессе выполнения возникли ошибки (не бизнес-логики), то возвращается Error Response пакет и соединение закрывается.
Каждая команда может быть 2 типов: требует подтверждения и немедленная. Для немедленных команд поток выполнения одинаков. Для требующих подтверждения собственные.
Этот тип команд выполняется сразу, как только принимается сервером. Для нее не нужно подтверждения.
Алгоритм:
- Клиент отправляет Command Request пакет с нужной командой
- Сервер принимает команду и выполняет ее
- Сервер отправляет клиенту:
- Либо Command Response клиенту с данными результатов работы
- Либо Ok сигнализирующий об успешном выполнении команды
Что должна возвращать команда после успешного выполнения (CommandResponse/Ok) прописано для каждой отдельно.
sequenceDiagram
actor Клиент
participant Сервер
Клиент->>Сервер: CommandRequest
Сервер ->> Клиент: CommandResponse/Ok
Это команда для вставки новой записи в очередь.
После того как клиент отправил Command Request с командой Enqueue (и сервер его принял), он должен дополнительно отправить Acknowledge пакет и только после этого запись будет добавлена.
Алгоритм:
- Клиент отправляет Command Request с командой Enqueue
- Сервер принимает запрос
- Сервер отправляет Ok пакет
- Если клиент отправляет Acknowledge:
- Сервер выполняет запись в очередь
- Сервер отправляет Command Response пакет с результатом выполнения команды
- Иначе, если клиент отправляет Negative Acknowledge
- Сервер отправляет Ok пакет
Замечание: пока нет дополнительных проверок на то, можно ли выполнить запрос или нет. Например, проверить, что такая очередь существует. Может в будущем добавится, но семантика сейчас такая, что выполнение просто откладывается до получения нужного пакета.
sequenceDiagram
actor Клиент
participant Сервер
Клиент->>Сервер: CommandRequest(Enqueue)
Сервер->>Клиент: Ok
Клиент ->> Сервер: Ack/Nack
Сервер ->> Клиент: CommandResponse
Это команда для чтения записей из очереди. На данный момент чтение происходит по 1 записи за раз, т.е. нельзя сразу прочитать пачкой и последовательно их подтверждать.
Если клиент хочет прочитать запись из какой-либо очереди, то он отправляет Command Request с Dequeue командой. В этой команде можно указать таймаут чтения:
0
- выключить ожидание и получить ответ сразу- другие значения - брокер будет ожидать указанное число мс прежде чем вернуть ответ.
Если по истечению таймаута, новых записей не было, то сервер вернет Dequeue Response с пустым ответом и дальнейшая работа прекращается.
Когда из очереди была прочитана запись, то сервер отправляет Command Response с прочитанной записью. По окончании обработки прочитанной записи, клиент отправляет Acknowledge пакет на сервер и сервер коммитит выполнение команды (запись в логе об удалении). В конце, сервер отправляет Ok пакет клиенту.
Алгоритм:
- Клиент отправляет Command Request с Dequeue командой
- Если в очереди не было записей и был указан таймаут:
- Сервер ждет новых записей указанное время
- Сервер отправляет Command Response клиенту с прочитанной записью
- Если записей прочитано не было, то возвращается пустой ответ (пустая запись)
- Алгоритм заканчивается
- Если клиент отправляет Acknowledge серверу:
- Сервер коммитит выполнение команды (сохраняет команду в логе)
- Иначе, если Negative Acknowledge:
- Сервер прекращает обработку этой команды
- Сервер отправляет Ok пакет клиенту
sequenceDiagram
actor Клиент
participant Сервер
Клиент->>Сервер: CommandRequest(Dequeue)
Note right of Сервер: Таймаут
Сервер->>Клиент: CommandResponse(Dequeue)
opt Записть прочитана
Клиент ->> Сервер: Ack/Nack
Сервер ->> Клиент: Ok
end
Замечание: если в очереди не было записей, то ничего подтверждать ничего не нужно, т.к. удаления не произошло
В этой секции описаны пакеты, которые используются для обмена между клиентом и сервером.
Пакет, передающий основной запрос к узлу. Тело представляет собой сериализованные данные команды. После маркера идет 4 байтное целое число, определяющее длину тела.
Формат пакета:
Маркер | Данные |
---|---|
Byte('C') | ... |
В поле Данные
содержится сериализованная команда.
Команды запроса представлены в отдельной документации.
Пакет, передающий ответ на запрос операции. После маркера указывается 4 байтная длина тела запроса. Содержимое тела зависит от переданного прежде Data Request
Формат пакета:
Marker | Payload |
---|---|
Byte('c') | ... |
Возможные ответы представлены в документации команд
Пакет, посылаемый клиентом, когда необходимо зафиксировать результат выполнения команды. Состоит из единственного байта-маркера.
Формат пакета:
Маркер |
---|
Byte('Q') |
Пакет, посылаемый клиентом, когда необходимо отменить выполнение команды. Состоит из единственного байта-маркера.
Формат пакета:
Маркер |
---|
Byte('N') |
Пакет, сигнализирующий о принятом запросе. В основном используется как промежуточное звено в процессе обработки запросов (сигнал о принятом пакете).
Маркер |
---|
Byte('k') |
Пакет посылаемый клиенту сервером, если возникла ошибка при выполнении.
В поле Код ошибки
содержится число описывающее какая ошибка произошла.
Если необходимо, то дополнительное описание ошибки представлено в поле Детали
.
Формат:
Marker | Код ошибки | Детали |
---|---|---|
Byte('e') | Int32 | String |
Пакет отправляется сервером, если на узел не являющийся лидером в кластере пришла модифицирующая команда.
В поле Id лидера
указывается ID узла лидера текущего кластера. Запросы нужно адресовать лидеру.
Формат:
Маркер | Id лидера |
---|---|
Byte('l') | Int32 |
В случае, если на момент запроса лидера не было обнаружено, то поле Id лидера
равняется -1
.
Пакет отправляется клиентом после установления соединения. Используется для авторизации клиента сервером.
Формат:
Marker | AuthType | Data |
---|---|---|
Byte('A') | Byte | .... |
Поле 'AuthorizationType' является маркером алгоритма авторизации. Поле 'Data' зависит от значения поля 'AuthorizationType' и в зависимости от типа может содержать любые значения.
Текущие методы авторизации
Маркер | Описание | Поле 'Data' |
---|---|---|
Byte('N') | Без авторизации | Тело отсутствует |
Отправляется сервером по завершении процесса авторизации. Используется для сигнализации клиенту о завершении процесса авторизации и отправке результата авторизации.
Формат:
Marker | Success | Reason |
---|---|---|
Byte('a') | Bool | String |
Success
- успешно ли завершился процесс авторизации. Если значение false
, то поле Reason
присутствует и содержит описание ошибки авторизации.
Если авторизация прошла неуспешно, то сервер закрывает соединение.
Отправляется клиентом после успешного процесса авторизации. Требуется для проверки версии и выставлении настроек для общения с сервером.
На текущий момент требуется только для проверки версии
Формат:
Marker | MajorVersion | MinorVersion | PatchVersion |
---|---|---|---|
Byte('B') | Int32 | Int32 | Int32 |
Первые 3 числа в пакете указывают на версию клиента. В TaskFlux используется семантическое версионирование.
Отправляется сервером в ответ на BootstrapRequest
пакет.
Формат
Marker | Success | Reason |
---|---|---|
Byte('b') | Bool | String |
Поле Success
указывает на успешность выставления настроек.
Если поле Success
выставлено в true
, то поле Reason
отсутствует.
Отправляется клиентом для получения метаданных кластера. Необходим, когда клиент хочет получить данные для дальнейшей коммуникации с узлами кластера.
Формат:
Маркер |
---|
Byte('M') |
Отправляется узлом в ответ на ClusterMetadataResponse пакет. В нем указывается список адресов узлов кластера и Id текущего лидера кластера.
Формат:
Маркер | Адреса | Id лидера | Id текущего узла |
---|---|---|---|
Byte('m') | Array<String> | Int32 | Int32 |
Поле "Адреса" содержится массив строк. Каждая строка может быть либо IP адресом, либо названием хоста.
Поле "Id лидера" содержится Id текущего лидера кластера. Если все биты поля выставлены в 1, то это значит текущего лидера нет.
Поле "Id текущего узла" содержит Id узла, вернувшего ответ.