Клиент AC для системы обмена сообщениями NATS.
Перейдите сюда, чтобы просмотреть онлайн-документацию и просмотреть часто задаваемые вопросы.
Эта реализация клиента NATS во многом основана на клиенте NATS GO. Имеется поддержка Mac OS/X, Linux и Windows (хотя у нас нет конкретной матрицы поддержки платформ).
Доступно несколько менеджеров пакетов с клиентской библиотекой NATS C. Если вы знаете кого-то, которого нет в этом списке, отправьте PR, чтобы добавить его!
Сначала загрузите исходный код:
git clone [email protected]:nats-io/nats.c.git .
Для сборки библиотеки используйте CMake. Обратите внимание, что по умолчанию API потоковой передачи NATS будет создан и включен в библиотеку NATS. См. ниже, если вы не хотите создавать API, связанные с потоковой передачей.
Убедитесь, что CMake добавлен в ваш путь. При сборке в Windows откройте командную оболочку из меню «Инструменты Visual Studio» и выберите соответствующую командную оболочку (x64 или x86 для 64- или 32-разрядных сборок соответственно). Вам также, вероятно, потребуется запустить это с правами администратора.
Создайте каталог build
(подойдет любое имя) из корневого дерева исходного кода и cd
в него. Затем введите эту команду в первый раз:
cmake ..
В некоторых архитектурах может возникнуть ошибка компиляции mutex.co
поскольку нет поддержки инструкции ассемблера, которую мы используем для получения результата при попытке получить блокировку.
Вы можете получить такую ошибку сборки:
/tmp/cc1Yp7sD.s: Assembler messages:
/tmp/cc1Yp7sD.s:302: Error: selected processor does not support ARM mode `yield'
src/CMakeFiles/nats_static.dir/build.make:542: recipe for target 'src/CMakeFiles/nats_static.dir/unix/mutex.c.o' failed
Если это так, вы можете решить эту проблему, включив флаг NATS_BUILD_NO_SPIN
(или используйте -DNATS_NO_SPIN
, если вы компилируете без CMake):
cmake .. -DNATS_BUILD_NO_SPIN=ON
Если вы ранее собрали библиотеку, вам может потребоваться выполнить make clean
или просто удалить и заново создать каталог сборки перед выполнением команды cmake.
Для сборки в Windows вам нужно будет выбрать генератор сборки. Например, чтобы выбрать nmake
, вы должны запустить:
cmake .. -G "NMake Makefiles"
Запуск cmake -h
даст вам список возможных опций и имена всех генераторов.
Альтернативно вы можете запустить версию с графическим интерфейсом. Из той же командной оболочки сборки запустите графический интерфейс:
c:program files (x86)CMakebincmake-gui.exe
Если вы начали с пустого каталога сборки, вам нужно будет выбрать исходный каталог и каталог сборки, а затем нажать Configure
. Здесь вы сможете выбрать из раскрывающегося списка имя генератора сборки. Когда закончите, нажмите Generate
. Затем вы можете вернуться в командную оболочку или Visual Studio и выполнить сборку.
Чтобы изменить некоторые параметры сборки, вам необходимо отредактировать кеш и выполнить повторную сборку.
make edit_cache
Обратите внимание: если вы используете Windows и выбрали «NMake Makefiles», замените все следующие ссылки на make
на nmake
.
Редактирование кеша позволяет выбрать тип сборки (Отладка, Релиз и т. д.), архитектуру (64 или 32 бит) и т. д.
Цель по умолчанию будет собирать все, то есть статические и общие библиотеки NATS, а также примеры и тестовую программу. Каждый из них расположен в соответствующих каталогах вашего каталога сборки: src
, examples
и test
.
make install
Копирует статические и общие библиотеки в папку install/lib
и общедоступные заголовки в install/include
.
По умолчанию библиотека построена с поддержкой TLS. Вы можете отключить это из графического интерфейса cmake make edit_cache
и переключить параметр NATS_BUILD_WITH_TLS
на OFF
или передать этот параметр непосредственно команде cmake
:
cmake .. -DNATS_BUILD_WITH_TLS=OFF
Начиная с 2.0.0
, при сборке с поддержкой TLS/SSL всегда проверяется ожидаемое имя хоста сертификата сервера. Это означает, что имя хоста, указанное в URL-адресах или через опцию natsOptions_SetExpectedHostname()
будет использоваться для проверки имени хоста, присутствующего в сертификате. До 2.0.0
имя хоста проверялось только в том случае, если была вызвана опция natsOptions_SetExpectedHostname()
.
Хотя мы рекомендуем оставить новое поведение по умолчанию, вы можете восстановить предыдущее поведение, создав библиотеку с отключенной этой опцией:
cmake .. -DNATS_BUILD_TLS_FORCE_HOST_VERIFY=OFF
Клиент NATS C создан с использованием API из библиотеки OpenSSL. По умолчанию мы используем API 3.0+
. Поскольку OpenSSL 1.0.2
больше не поддерживается, начиная с версии NATS C Client v3.6.0
, для переменной CMake NATS_BUILD_TLS_USE_OPENSSL_1_1_API
теперь установлено значение ON
по умолчанию (если вы настраиваете новую среду) и будут использоваться API OpenSSL из 1.1+
/ 3.0+
API. Вы по-прежнему сможете скомпилировать библиотеку OpenSSL 1.0.2
, установив для этого параметра CMake значение OFF
:
cmake .. -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=OFF
Переменная NATS_BUILD_TLS_USE_OPENSSL_1_1_API
устарела, а это означает, что в будущем эта опция будет просто удалена и будут использоваться только API OpenSSL 3.0+
. Код в библиотеке, использующий старые API OpenSSL, также будет удален.
Обратите внимание, что переменная NATS_BUILD_WITH_TLS_CLIENT_METHOD
, которая считалась устаревшей в v2.0.0
, теперь удалена.
Поскольку клиент NATS C динамически подключается к библиотеке OpenSSL, вам необходимо убедиться, что вы затем запускаете свое приложение с библиотекой OpenSSL 1.1+/3.0+.
Если вы хотите создать ссылку на статическую библиотеку OpenSSL, вам необходимо удалить CMakeCache.txt
и заново создать его с помощью дополнительной опции:
rm CMakeCache.txt
cmake .. -DNATS_BUILD_OPENSSL_STATIC_LIBS=ON
Затем вызовите make
(или его эквивалент в зависимости от вашей платформы), и это должно гарантировать, что библиотека (и примеры и/или исполняемый файл набора тестов) связаны с библиотекой OpenSSL, если она была найдена CMake.
При сборке библиотеки с поддержкой потоковой передачи библиотека NATS использует библиотеку libprotobuf-c. Когда cmake запускается в первый раз (или после удаления CMakeCache.txt
и повторного вызова cmake ..
), он ищет библиотеку libprotobuf-c. Если он его не находит, выводится сообщение и процесс сборки завершается неудачно. CMake ищет библиотеку в каталогах, где обычно находятся библиотеки. Однако если вы хотите указать конкретный каталог, в котором находится библиотека, вам необходимо сделать следующее:
cmake .. -DNATS_PROTOBUF_DIR=
Статическая библиотека будет использоваться по умолчанию. Если вы хотите это изменить или если у библиотеки нет ожидаемого имени, вам нужно сделать следующее:
# Use the library named mylibproto.so located at /my/location
cmake .. -DNATS_PROTOBUF_LIBRARY=/my/location/mylibproto.so
Их можно объединить, если заголовок включения находится в другом каталоге.
# Use the library named mylibproto.so located at /my/location and the directory protobuf-c/ containing protobuf-c.h located at /my/other/location
cmake .. -DNATS_PROTOBUF_LIBRARY=/my/location/mylibproto.so -DNATS_PROTOBUF_DIR=/my/other/location
Если вы не хотите создавать API потоковой передачи NATS для включения в библиотеку NATS:
cmake .. -DNATS_BUILD_STREAMING=OFF
При использовании новых функций безопасности NATS 2.0 библиотеке необходимо подписать некоторый «nonce», отправленный сервером во время подключения или повторного подключения. Мы используем подпись с открытым ключом Ed25519. В состав библиотеки входит код для выполнения подписи. В большинстве случаев все будет в порядке, но если производительность является проблемой (особенно если вы планируете часто использовать функцию natsConnection_Sign()
), у вас будет возможность выполнить сборку с помощью библиотеки Libsodium.
Следуйте инструкциям по установке библиотеки libsodium здесь.
В macOS вы можете использовать brew
:
brew install libsodium
В Linux вы можете использовать apt-get
apt-get install libsodium-dev
После установки вы можете пересобрать клиент NATS C, сначала включив использование библиотеки libsodium:
cmake .. -DNATS_BUILD_USE_SODIUM=ON
Если у вас установлена библиотека libsodium в нестандартном месте, которое CMake не может найти, вы можете указать расположение этого каталога:
cmake .. -DNATS_BUILD_USE_SODIUM=ON -DNATS_SODIUM_DIR=/my/path/to/libsodium
На платформах, где доступен valgrind
, вы можете запускать тесты с проверкой памяти. Вот пример:
make test ARGS="-T memcheck"
Или вы можете напрямую вызвать программу ctest
:
ctest -T memcheck -V -I 1,4
Приведенная выше команда запускает тесты с помощью valgrind
( -T memcheck
), с подробным выводом ( -V
) и запускает тесты от 1 до 4 ( -I 1,4
).
Если вы добавляете тест в test/test.c
, вам необходимо добавить его в файл list_test.txt
. Каждая запись содержит только имя теста, функция должна иметь одинаковое имя с префиксом test_
. Список расположен в алфавитном порядке, но это не обязательно, добавлять можно где угодно.
Если вы добавляете тест, его следует добавить в list_bench.txt
. Эти тесты помечены по-разному ( -L 'bench'
) и выполняются отдельно на CI.
Вам необходимо перезапустить cmake
, чтобы изменения вступили в силу:
cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ivan/nats.c/build
Вы можете использовать следующие переменные среды, чтобы влиять на поведение набора тестов.
При работе с проверкой памяти время меняется и общая производительность снижается. Следующая переменная позволяет набору тестов корректировать некоторые значения, используемые во время теста:
export NATS_TEST_VALGRIND=yes
В Windows он будет set
вместо export
.
При запуске тестов в подробном режиме следующая переменная среды позволяет вам видеть выходные данные сервера внутри самого теста. Без этой опции вывод сервера отключается:
export NATS_TEST_KEEP_SERVER_OUTPUT=yes
Если вы хотите изменить имя исполняемого файла сервера по умолчанию ( nats-server.exe
) или указать конкретное местоположение, используйте эту переменную среды:
set NATS_TEST_SERVER_EXE=c:testnats-server.exe
Публичный API документирован с использованием Doxygen.
Чтобы создать документацию, перейдите в каталог doc
и введите следующую команду:
doxygen DoxyFile.NATS.Client
Если вы переключаете сборку API потоковой передачи и документация больше не соответствует создаваемой, вы можете обновить документацию, переключив флаг сборки NATS_UPDATE_DOC
, и перестроить документацию.
Из каталога сборки:
cmake .. -DNATS_UPDATE_DOC=ON
make
cd /doc
doxygen DoxyFile.NATS.Client
Сгенерированная документация будет расположена в каталоге html
. Чтобы просмотреть документацию, укажите в браузере файл index.html
в этом каталоге.
Перейдите сюда для онлайн-документации.
Исходный код также достаточно документирован.
В этом разделе перечислены важные изменения, такие как уведомления об устаревании и т. д.
2.0.0
В этой версии представлены концепции безопасности, используемые NATS Server 2.0.0
, и поэтому она соответствует версии сервера. Были введены новые API, но наиболее важным изменением является новое поведение по умолчанию с TLS-соединениями:
При установке безопасного соединения имя хоста сертификата сервера теперь всегда проверяется, независимо от того, вызвал ли пользователь natsOptions_SetExpectedHostname()
. Это может привести к поломке приложений, которые, например, использовали IP-адрес для подключения к серверу, в сертификате которого было только имя хоста. Эту проблему можно решить, изменив ваше приложение на использование имени хоста в URL-адресе или использование natsOptions_SetExpectedHostname()
. Если это невозможно, вы можете восстановить старое поведение, создав библиотеку с отключенным новым поведением. См. #tls-support для получения дополнительной информации.
Раньше этот репозиторий включал предварительно скомпилированные библиотеки libprotobuf-c для macOS, Linux и Windows, а также файлы заголовков (в каталоге /pbuf
). Сейчас мы удалили этот каталог и требуем, чтобы пользователь установил библиотеку libprotobuf-c отдельно. См. инструкции по сборке, чтобы указать расположение библиотеки, если CMake не может найти ее напрямую.
1.8.0
natsConnStatus
имеют префикс NATS_CONN_STATUS_
. Если ваше приложение не использует ссылку на какое-либо исходное значение, например CONNECTED
или CLOSED
и т. д., то вам ничего не нужно делать. Если да, то у вас есть два варианта:NATS_BUILD_NO_PREFIX_CONNSTS
. Это можно сделать из каталога сборки следующим образом: cmake .. -DNATS_BUILD_NO_PREFIX_CONNSTS=ON
В каталоге examples/getstarted
есть набор простых, полнофункциональных, но очень простых примеров. Цель — продемонстрировать, насколько просто использовать API.
Более сложный набор примеров находится в каталоге examples/
, и его также можно использовать для тестирования клиентской библиотеки.
Обратите внимание, что для простоты здесь не выполняется проверка ошибок.
natsConnection * nc = NULL ;
natsSubscription * sub = NULL ;
natsMsg * msg = NULL ;
// Connects to the default NATS Server running locally
natsConnection_ConnectTo ( & nc , NATS_DEFAULT_URL );
// Connects to a server with username and password
natsConnection_ConnectTo ( & nc , "nats://ivan:secret@localhost:4222" );
// Connects to a server with token authentication
natsConnection_ConnectTo ( & nc , "nats://myTopSecretAuthenticationToken@localhost:4222" );
// Simple publisher, sending the given string to subject "foo"
natsConnection_PublishString ( nc , "foo" , "hello world" );
// Publish binary data. Content is not interpreted as a string.
char data [] = { 1 , 2 , 0 , 4 , 5 };
natsConnection_Publish ( nc , "foo" , ( const void * ) data , 5 );
// Simple asynchronous subscriber on subject foo, invoking message
// handler 'onMsg' when messages are received, and not providing a closure.
natsConnection_Subscribe ( & sub , nc , "foo" , onMsg , NULL );
// Simple synchronous subscriber
natsConnection_SubscribeSync ( & sub , nc , "foo" );
// Using a synchronous subscriber, gets the first message available, waiting
// up to 1000 milliseconds (1 second)
natsSubscription_NextMsg ( & msg , sub , 1000 );
// Destroy any message received (asynchronously or synchronously) or created
// by your application. Note that if 'msg' is NULL, the call has no effect.
natsMsg_Destroy ( msg );
// Unsubscribing
natsSubscription_Unsubscribe ( sub );
// Destroying the subscription (this will release the object, which may
// result in freeing the memory). After this call, the object must no
// longer be used.
natsSubscription_Destroy ( sub );
// Publish requests to the given reply subject:
natsConnection_PublishRequestString ( nc , "foo" , "bar" , "help!" );
// Sends a request (internally creates an inbox) and Auto-Unsubscribe the
// internal subscriber, which means that the subscriber is unsubscribed
// when receiving the first response from potentially many repliers.
// This call will wait for the reply for up to 1000 milliseconds (1 second).
natsConnection_RequestString ( & reply , nc , "foo" , "help" , 1000 );
// Closing a connection (but not releasing the connection object)
natsConnection_Close ( nc );
// When done with the object, free the memory. Note that this call
// closes the connection first, in other words, you could have simply
// this call instead of natsConnection_Close() followed by the destroy
// call.
natsConnection_Destroy ( nc );
// Message handler
void
onMsg ( natsConnection * nc , natsSubscription * sub , natsMsg * msg , void * closure )
{
// Prints the message, using the message getters:
printf ( "Received msg: %s - %.*sn" ,
natsMsg_GetSubject ( msg ),
natsMsg_GetDataLength ( msg ),
natsMsg_GetData ( msg ));
// Don't forget to destroy the message!
natsMsg_Destroy ( msg );
}
Поддержка JetStream начинается с версии v3.0.0
библиотеки и NATS Server v2.2.0+
, хотя для получения конкретных кодов ошибок JetStream требуется сервер версии v2.3.0+
. Некоторые параметры конфигурации доступны только начиная с v2.3.3
, поэтому мы рекомендуем вам использовать последнюю версию NATS Server, чтобы улучшить работу.
Посмотрите примеры с именем js-xxx.c
в каталоге examples
, чтобы узнать, как использовать API. Новые объекты и API полностью описаны в онлайн-документации.
// Connect to NATS
natsConnection_Connect ( & conn , opts );
// Initialize and set some JetStream options
jsOptions jsOpts ;
jsOptions_Init ( & jsOpts );
jsOpts . PublishAsync . MaxPending = 256 ;
// Create JetStream Context
natsConnection_JetStream ( & js , conn , & jsOpts );
// Simple Stream Publisher
js_Publish ( & pa , js , "ORDERS.scratch" , ( const void * ) "hello" , 5 , NULL , & jerr );
// Simple Async Stream Publisher
for ( i = 0 ; i < 500 ; i ++ )
{
js_PublishAsync ( js , "ORDERS.scratch" , ( const void * ) "hello" , 5 , NULL );
}
// Wait for up to 5 seconds to receive all publish acknowledgments.
jsPubOptions_Init ( & jsPubOpts );
jsPubOpts . MaxWait = 5000 ;
js_PublishAsyncComplete ( js , & jsPubOpts );
// One can get the list of all pending publish async messages,
// to either resend them or simply destroy them.
natsMsgList pending ;
s = js_PublishAsyncGetPendingList ( & pending , js );
if ( s == NATS_OK )
{
int i ;
for ( i = 0 ; i < pending . Count ; i ++ )
{
// There could be a decision to resend these messages or not.
if ( your_decision_to_resend ( pending . Msgs [ i ]))
{
// If the call is successful, pending.Msgs[i] will be set
// to NULL so destroying the pending list will not destroy
// this message since the library has taken ownership back.
js_PublishMsgAsync ( js , & ( pending . Msgs [ i ]), NULL );
}
}
// Destroy the pending list object and all messages still in that list.
natsMsgList_Destroy ( & pending );
}
// To create an asynchronous ephemeral consumer
js_Subscribe ( & sub , js , "foo" , myMsgHandler , myClosure , & jsOpts , NULL , & jerr );
// Same but use a subscription option to ask the callback to not do auto-ack.
jsSubOptions so ;
jsSubOptions_Init ( & so );
so . ManualAck = true;
js_Subscribe ( & sub , js , "foo" , myMsgHandler , myClosure , & jsOpts , & so , & jerr );
// Or to bind to an existing specific stream/durable:
jsSubOptions_Init ( & so );
so . Stream = "MY_STREAM" ;
so . Consumer = "my_durable" ;
js_Subscribe ( & sub , js , "foo" , myMsgHandler , myClosure , & jsOpts , & so , & jerr );
// Synchronous subscription:
js_SubscribeSync ( & sub , js , "foo" , & jsOpts , & so , & jerr );
jsStreamConfig cfg ;
// Connect to NATS
natsConnection_Connect ( & conn , opts );
// Create JetStream Context
natsConnection_JetStream ( & js , conn , NULL );
// Initialize the configuration structure.
jsStreamConfig_Init ( & cfg );
// Provide a name
cfg . Name = "ORDERS" ;
// Array of subjects and its size
cfg . Subjects = ( const char * [ 1 ]){ "ORDERS.*" };
cfg . SubjectsLen = 1 ;
// Create a Stream. If you are not interested in the returned jsStreamInfo object,
// you can pass NULL.
js_AddStream ( NULL , js , & cfg , NULL , & jerr );
// Update a Stream
cfg . MaxBytes = 8 ;
js_UpdateStream ( NULL , js , & cfg , NULL , & jerr );
// Delete a Stream
js_DeleteStream ( js , "ORDERS" , NULL , & jerr );
ЭКСПЕРИМЕНТАЛЬНАЯ ФУНКЦИЯ! Мы оставляем за собой право изменять API без обязательного изменения основной версии библиотеки.
Хранилище KeyValue — это материализованное представление, основанное на JetStream. Ведро — это поток, а ключи — это субъекты внутри этого потока.
Для некоторых функций требуется сервер NATS v2.6.2
, поэтому мы рекомендуем вам использовать последнюю версию сервера NATS, чтобы улучшить работу.
Новые объекты и API полностью описаны в онлайн-документации.
Пример создания хранилища KeyValue:
jsCtx * js = NULL ;
kvStore * kv = NULL ;
kvConfig kvc ;
// Assume we got a JetStream context in `js`...
kvConfig_Init ( & kvc );
kvc . Bucket = "KVS" ;
kvc . History = 10 ;
s = js_CreateKeyValue ( & kv , js , & kvc );
// Do some stuff...
// This is to free the memory used by `kv` object,
// not delete the KeyValue store in the server
kvStore_Destroy ( kv );
Это показывает, как «привязаться» к существующему:
jsCtx * js = NULL ;
kvStore * kv = NULL ;
// Assume we got a JetStream context in `js`...
s = js_KeyValue ( & kv , ks , "KVS" );
// Do some stuff...
// This is to free the memory used by `kv` object,
// not delete the KeyValue store in the server
kvStore_Destroy ( kv );
Вот как удалить хранилище KeyValue на сервере:
jsCtx * js = NULL ;
// Assume we got a JetStream context in `js`...
s = js_DeleteKeyValue ( js , "KVS" );
Вот как можно задать значение для данного ключа:
kvStore * kv = NULL ;
uint64_t rev = 0 ;
// Assume we got a kvStore...
s = kvStore_PutString ( & rev , kv , "MY_KEY" , "my value" );
// If the one does not care about getting the revision, pass NULL:
s = kvStore_PutString ( NULL , kv , "MY_KEY" , "my value" );
Вышеупомянутое помещает значение для данного ключа, но если вместо этого кто-то хочет убедиться, что значение помещается для ключа, только если он никогда не существовал раньше, можно было бы вызвать:
// Same note than before: if "rev" is not needed, pass NULL:
s = kvStore_CreateString ( & rev , kv , "MY_KEY" , "my value" );
Ключ можно обновить тогда и только тогда, когда последняя ревизия на сервере соответствует той, которая была передана в этот API:
// This would update the key "MY_KEY" with the value "my updated value" only if the current revision (sequence number) for this key is 10.
s = kvStore_UpdateString ( & rev , kv , "MY_KEY" , "my updated value" , 10 );
Вот как получить ключ:
kvStore * kv = NULL ;
kvEntry * e = NULL ;
// Assume we got a kvStore...
s = kvStore_Get ( & e , kv , "MY_KEY" );
// Then we can get some fields from the entry:
printf ( "Key value: %sn" , kvEntry_ValueString ( e ));
// Once done with the entry, we need to destroy it to release memory.
// This is NOT deleting the key from the server.
kvEntry_Destroy ( e );
Вот как очистить ключ:
kvStore * kv = NULL ;
// Assume we got a kvStore...
s = kvStore_Purge ( kv , "MY_KEY" );
Это приведет к удалению ключа на сервере:
kvStore * kv = NULL ;
// Assume we got a kvStore...
s = kvStore_Delete ( kv , "MY_KEY" );
Чтобы создать «наблюдателя» для данного ключа:
kvWatcher * w = NULL ;
kvWatchOptions o ;
// Assume we got a kvStore...
// Say that we are not interested in getting the
// delete markers...
// Initialize a kvWatchOptions object:
kvWatchOptions_Init ( & o );
o . IgnoreDeletes = true;
// Create the watcher
s = kvStore_Watch ( & w , kv , "foo.*" , & o );
// Check for error..
// Now get updates:
while ( some_condition )
{
kvEntry * e = NULL ;
// Wait for the next update for up to 5 seconds
s = kvWatcher_Next ( & e , w , 5000 );
// Do something with the entry...
// Destroy to release memory
kvEntry_Destroy ( e );
}
// When done with the watcher, it needs to be destroyed to release memory:
kvWatcher_Destroy ( w );
Чтобы получить историю ключа:
kvEntryList l ;
int i ;
// The list is defined on the stack and will be initilized/updated by this call:
s = kvStore_History ( & l , kv , "MY_KEY" , NULL );
for ( i = 0 ; i < l . Count ; i ++ )
{
kvEntry * e = l . Entries [ i ];
// Do something with the entry...
}
// When done with the list, call this to free entries and the content of the list.
kvEntryList_Destroy ( & l );
// In order to set a timeout to get the history, we need to do so through options:
kvWatchOptions o ;
kvWatchOptions_Init ( & o );
o . Timeout = 5000 ; // 5 seconds.
s = kvStore_History ( & l , kv , "MY_KEY" , & o );
Вот как вы получите ключи от ведра:
kvKeysList l ;
int i ;
// If no option is required, pass NULL as the last argument.
s = kvStore_Keys ( & l , kv , NULL );
// Check error..
// Go over all keys:
for ( i = 0 ; i < l . Count ; i ++ )
printf ( "Key: %sn" , l . Keys [ i ]);
// When done, list need to be destroyed.
kvKeysList_Destroy ( & l );
// If option need to be specified:
kvWatchOptions o ;
kvWatchOptions_Init ( & o );
o . Timeout = 5000 ; // 5 seconds.
s = kvStore_Keys ( & l , kv , & o );
Заголовки доступны при подключении к серверам версии 2.2.0+.
Они очень напоминают заголовки http. Они представляют собой карту пар ключ/значение, где значение представляет собой массив строк.
Заголовки позволяют пользователям добавлять метаинформацию о сообщении, не мешая полезной нагрузке сообщения.
Обратите внимание: если приложение попытается отправить сообщение с заголовком при подключении к серверу, который их не понимает, вызов публикации вернет ошибку NATS_NO_SERVER_SUPPORT
.
Существует API, позволяющий узнать, поддерживает ли сервер, к которому в данный момент подключено, заголовки:
natsStatus s = natsConnection_HasHeaderSupport ( conn );
if ( s == NATS_NO_SERVER_SUPPORT )
// deal with server not supporting this feature.
Если сервер понимает заголовки, но собирается доставить сообщение клиенту, который этого не делает, заголовки удаляются, чтобы старые клиенты все еще могли получать сообщение. Важно, чтобы все клиенты и серверы имели версию, поддерживающую заголовки, если приложения полагаются на заголовки.
Для получения более подробной информации об API заголовков посмотрите пример: examples/getstarted/headers.c
.
Подстановочный знак *
соответствует любому токену на любом уровне субъекта:
natsConnection_Subscribe ( & sub , nc , "foo.*.baz" , onMsg , NULL );
Этот подписчик будет получать сообщения, отправленные на:
Однако он не будет получать сообщения о:
Подстановочный знак >
соответствует любой длине отказа субъекта и может быть только последним токеном.
natsConnection_Subscribe ( & sub , nc , "foo.>" , onMsg , NULL );
Этот подписчик получит любое сообщение, отправленное на:
Однако он не будет получать сообщения, отправленные на:
Публикация на эту тему приведет к тому, что два вышеуказанных подписчика получат сообщение:
natsConnection_PublishString ( nc , "foo.bar.baz" , "got it?" );
Все подписки с одинаковым именем очереди образуют группу очередей. Каждое сообщение будет доставлено только одному подписчику в каждой группе очереди с использованием сематики очереди. Вы можете иметь столько групп очередей, сколько пожелаете. Обычные абоненты продолжат работать как положено.
natsConnection_QueueSubscribe ( & sub , nc , "foo" , "job_workers" , onMsg , NULL );
(Обратите внимание, что для работы этих API библиотека должна быть собрана с поддержкой TLS, которая есть по умолчанию. Дополнительные сведения см. в главе «Сборка», посвященной сборке с поддержкой TLS или без нее).
Соединение SSL/TLS настраивается с помощью natsOptions
. В зависимости от желаемого уровня безопасности это может быть так же просто, как установка логического значения безопасности в значение true при вызове natsOptions_SetSecure()
.
Даже при полной безопасности (клиент проверяет сертификат сервера и сервер требует сертификатов клиента) настройка включает всего несколько вызовов.
// Here is the minimum to create a TLS/SSL connection:
// Create an options object.
natsOptions_Create ( & opts );
// Set the secure flag.
natsOptions_SetSecure ( opts , true);
// You may not need this, but suppose that the server certificate
// is self-signed and you would normally provide the root CA, but
// don't want to. You can disable the server certificate verification
// like this:
natsOptions_SkipServerVerification ( opts , true);
// Connect now...
natsConnection_Connect ( & nc , opts );
// That's it! On success you will have a secure connection with the server!
(...)
// This example shows what it takes to have a full SSL configuration,
// including server expected's hostname, root CA, client certificates
// and specific ciphers to use.
// Create an options object.
natsOptions_Create ( & opts );
// Set the secure flag.
natsOptions_SetSecure ( opts , true);
// For a server with a trusted chain built into the client host,
// simply designate the server name that is expected. Without this
// call, the server certificate is still verified, but not the
// hostname.
natsOptions_SetExpectedHostname ( opts , "localhost" );
// Instead, if you are using a self-signed cert and need to load in the CA.
natsOptions_LoadCATrustedCertificates ( opts , caCertFileName );
// If the server requires client certificates, provide them along with the
// private key, all in one call.
natsOptions_LoadCertificatesChain ( opts , certChainFileName , privateKeyFileName );
// You can also specify preferred ciphers if you want.
natsOptions_SetCiphers ( opts , "-ALL:HIGH" );
// Then simply pass the options object to the connect call:
natsConnection_Connect ( & nc , opts );
// That's it! On success you will have a secure connection with the server!