Коннекторы | Tarantool
Документация на русском языке
поддерживается сообществом
Коннекторы

Коннекторы

Коннекторы — это API, позволяющие использовать Tarantool с различными языками программирования.

Connectors can be divided into two groups – those maintained by the Tarantool team and those supported by the community. The Tarantool team maintains the high-level C API, the Go and Java connectors, and a synchronous Python connector. All other connectors are community-supported, which means that support for new Tarantool features may be delayed. Besides, the Tarantool support team cannot prioritize issues that arise while working through these connectors.

This chapter documents APIs for various programming languages:

Бинарный протокол передачи данных в Tarantool был разработан с учетом потребностей асинхронного ввода-вывода для облегчения интеграции с прокси-серверами. Каждый клиентский запрос начинается с бинарного заголовка переменной длины. В заголовке указывается идентификатор и тип запроса, идентификатор экземпляра, номер записи в журнале и т.д.

Также в заголовке обязательно указывается длина запроса, что облегчает обмен данными с клиентом или прокси. Ответ на запрос посылается по мере готовности. В заголовке ответа указывается тот же идентификатор и тип запроса, что и в изначальном запросе. По идентификатору легко соотнести запрос с ответом, даже если ответы приходят в произвольном порядке.

Вдаваться в тонкости реализации бинарного протокола нужно, только если вы разрабатываете новый коннектор для Tarantool. В остальных случаях достаточно взять уже существующий коннектор для нужного вам языка программирования. Такие коннекторы позволяют без труда хранить в формате Tarantool структуры данных из разных языков. Полное описание бинарного протокола в Tarantool хранится в дереве исходного кода в виде аннотированных форм Бэкуса — Наура (BNF-диаграмм). Подробные примеры и диаграммы всех запросов и ответов можно найти в описании бинарного протокола в Tarantool.

С помощью API Tarantool клиентские программы могут отправлять на адрес экземпляра пакеты с запросами и получать на них ответы. Пример ниже относится к клиентскому запросу box.space[513]:insert{'A', 'BB'}. Описания компонентов запроса, представленные в форме Бэкуса — Наура, вы найдете на странице о бинарном протоколе Tarantool.

Компонент Байт 0 Байт 1 Байт 2 Байт 3
код операции insert 02      
остальная часть заголовка
двузначное число: ID спейса cd 02 01  
код кортежа 21      
однозначное число: количество полей = 2 92      
односимвольная строка: поле[1] a1 41    
двухсимвольная строка: поле[2] a2 42 42  

Этот пакет можно отправить экземпляру Tarantool, а затем расшифровать ответ. Формат пакетов запроса и ответа также описан на странице о бинарном протоколе Tarantool. Однако проще и надежнее вызвать процедуру, которая сформирует готовый пакет с заданными параметрами. Например, она могла бы выглядеть так: response = tarantool_routine("insert", 513, "A", "B");. Для этого и существуют API для драйверов Perl, Python, PHP и т. д.

В этой главе приводятся примеры того, как можно установить соединение с сервером Tarantool с помощью коннекторов для языков Perl, PHP, Python, Node.js и C. Примеры содержат фиксированные значения и будут корректно работать только при следующих условиях:

  • Экземпляр (tarantool) запущен на локальной машине (localhost = 127.0.0.1), а прослушивание для него настроено на порту 3301 (box.cfg.listen = '3301').
  • В базе есть спейс examples с идентификатором 999 (box.space.examples.id = 999). Первичный индекс этого спейса построен по ключу числового типа (box.space[999].index[0].parts[1].type = "unsigned").
  • Пользователь „guest“ имеет разрешение на чтение и запись.

Можно легко соблюсти все условия, запустив экземпляр и выполнив следующий скрипт:

box.cfg{listen=3301}
box.schema.space.create('examples',{id=999})
box.space.examples:create_index('primary', {type = 'hash', parts = {1, 'unsigned'}})
box.schema.user.grant('guest','read,write','space','examples')
box.schema.user.grant('guest','read','space','_space')

При работе с любым Tarantool-коннектором функции, вызванные Tarantool, возвращают значения в формате MsgPack. Для функций, вызываемых через API коннектора, формат возвращаемых значений следующий: скалярные значения возвращаются в виде кортежей (идентификатор типа в формате MsgPack, затем значение); все прочие (не скалярные) значения возвращаются в виде групп кортежей (идентификатор массива в формате MsgPack, затем скалярные значения). Если функция вызывается в рамках бинарного протокола (с помощью команды eval), а не через API коннектора, формат возвращаемых ею значений не меняется.

В примере ниже создается Lua-функция. Поскольку эту функцию будет вызывать внешний пользователь „guest“ user, необходимо с помощью grant настроить права на исполнение. Функция возвращает пустой массив, строку-скаляр, два логических значения и короткое целое число. Значения соответствуют приведенным в таблице стандартных типов в MsgPack-кодировке.

tarantool> box.cfg{listen=3301}
2016-03-03 18:45:52.802 [27381] main/101/interactive I> ready to accept requests
---
...
tarantool> function f() return {},'a',false,true,127; end
---
...
tarantool> box.schema.func.create('f')
---
...
tarantool> box.schema.user.grant('guest','execute','function','f')
---
...

Следующая программа на C вызывает эту функцию. Хотя в примере приводится код на C, результат будет одинаковым, на каком бы языке ни была написана программа: Perl, PHP, Python, Go или Java.

#include <stdio.h>
#include <stdlib.h>
#include <tarantool/tarantool.h>
#include <tarantool/tnt_net.h>
#include <tarantool/tnt_opt.h>
void main() {
  struct tnt_stream *tnt = tnt_net(NULL);              /* Настройка */
  tnt_set(tnt, TNT_OPT_URI, "localhost:3301");
   if (tnt_connect(tnt) < 0) {                         /* Соединение */
       printf("Connection refused\n");
       exit(-1);
   }
   struct tnt_stream *arg; arg = tnt_object(NULL);     /* Формирование запроса */
   tnt_object_add_array(arg, 0);
   struct tnt_request *req1 = tnt_request_call(NULL);  /* Вызов функции f() */
   tnt_request_set_funcz(req1, "f");
   uint64_t sync1 = tnt_request_compile(tnt, req1);
   tnt_flush(tnt);                                     /* Отправка запроса */
   struct tnt_reply reply;  tnt_reply_init(&reply);    /* Получение ответа */
   tnt->read_reply(tnt, &reply);
   if (reply.code != 0) {
     printf("Call failed %lu.\n", reply.code);
     exit(-1);
   }
   const unsigned char *p= (unsigned char*)reply.data; /* Вывод ответа */
   while (p < (unsigned char *) reply.data_end)
   {
     printf("%x ", *p);
     ++p;
   }
   printf("\n");
   tnt_close(tnt);                                     /* Завершение */
   tnt_stream_free(arg);
   tnt_stream_free(tnt);
}

По завершении программа выведет на экран следующие значения:

dd 0 0 0 5 90 91 a1 61 91 c2 91 c3 91 7f

Первые пять байт, dd 0 0 0 5, представляют собой фрагмент данных в формате MsgPack и обозначают 32-битный заголовок массива со значением 5 (см. спецификацию формата MsgPack). Остальные значения описаны в таблице стандартных типов в MsgPack-кодировке.

Нашли ответ на свой вопрос?
Обратная связь