Cliente AC para el sistema de mensajería NATS.
Vaya aquí para obtener la documentación en línea y consulte las preguntas frecuentes.
Esta implementación del Cliente NATS se basa en gran medida en el Cliente NATS GO. Hay soporte para Mac OS/X, Linux y Windows (aunque no tenemos una matriz de soporte de plataforma específica).
Hay varios administradores de paquetes con la biblioteca cliente NATS C disponibles. Si conoce uno que no está en esta lista, envíe un PR para agregarlo.
Primero, descargue el código fuente:
git clone [email protected]:nats-io/nats.c.git .
Para construir la biblioteca, use CMake. Tenga en cuenta que, de forma predeterminada, la API de transmisión NATS se creará e incluirá en la biblioteca NATS. Consulte a continuación si no desea crear las API relacionadas con Streaming.
Asegúrese de que CMake esté agregado a su ruta. Si compila en Windows, abra un shell de comandos desde el menú Herramientas de Visual Studio y seleccione el shell de comandos apropiado (x64 o x86 para compilaciones de 64 o 32 bits respectivamente). Probablemente también necesitarás ejecutar esto con privilegios de administrador.
Cree un directorio build
(cualquier nombre funcionaría) desde el árbol de fuentes raíz y cd
a él. Luego emita este comando por primera vez:
cmake ..
En algunas arquitecturas, es posible que experimente un error de compilación para mutex.co
porque no hay soporte para las instrucciones del ensamblador que utilizamos para ceder cuando intentamos adquirir un bloqueo.
Es posible que obtenga este tipo de error de compilación:
/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
Si ese es el caso, puede resolver esto habilitando el indicador NATS_BUILD_NO_SPIN
(o use -DNATS_NO_SPIN
si compila sin CMake):
cmake .. -DNATS_BUILD_NO_SPIN=ON
Si ya había creado la biblioteca anteriormente, es posible que deba realizar una make clean
o simplemente eliminar y volver a crear el directorio de compilación antes de ejecutar el comando cmake.
Para compilar en Windows, deberá seleccionar el generador de compilación. Por ejemplo, para seleccionar nmake
, ejecutarías:
cmake .. -G "NMake Makefiles"
Ejecutar cmake -h
le dará la lista de opciones posibles y todos los nombres del generador.
Alternativamente, puede ejecutar la versión GUI. Desde ese mismo shell de comando de compilación , inicie la GUI:
c:program files (x86)CMakebincmake-gui.exe
Si comenzó con un directorio de compilación vacío, deberá seleccionar el directorio de origen y de compilación y luego hacer clic en Configure
. Aquí podrá seleccionar en el cuadro desplegable el nombre del generador de compilación. Cuando termine, haga clic en Generate
. Luego puede volver a su shell de comandos o a Visual Studio y compilar.
Para modificar algunas de las opciones de compilación, debe editar el caché y reconstruirlo.
make edit_cache
Tenga en cuenta que si compila en Windows y ha seleccionado "NMake Makefiles", reemplace todas las siguientes referencias a make
con nmake
.
Editar el caché le permite seleccionar el tipo de compilación (depuración, lanzamiento, etc.), la arquitectura (64 o 32 bits), etc.
El objetivo predeterminado construirá todo, es decir, las bibliotecas NATS estáticas y compartidas y también los ejemplos y el programa de prueba. Cada uno está ubicado en sus respectivos directorios bajo su directorio de compilación: src
, examples
y test
.
make install
Copiará las bibliotecas estáticas y compartidas en la carpeta install/lib
y los encabezados públicos en install/include
.
De forma predeterminada, la biblioteca está construida con soporte TLS. Puede desactivar esto desde la interfaz gráfica de usuario de cmake make edit_cache
y cambiar la opción NATS_BUILD_WITH_TLS
a OFF
, o pasar la opción directamente al comando cmake
:
cmake .. -DNATS_BUILD_WITH_TLS=OFF
A partir de 2.0.0
, cuando se compila con soporte TLS/SSL, el nombre de host esperado del certificado del servidor siempre se verifica. Significa que el nombre de host proporcionado en las URL o mediante la opción natsOptions_SetExpectedHostname()
se utilizará para verificar el nombre de host presente en el certificado. Antes de 2.0.0
, el nombre de host se verificaba solo si se invocaba la opción natsOptions_SetExpectedHostname()
.
Aunque recomendamos dejar el nuevo comportamiento predeterminado, puedes restaurar el comportamiento anterior creando la biblioteca con esta opción desactivada:
cmake .. -DNATS_BUILD_TLS_FORCE_HOST_VERIFY=OFF
El cliente NATS C se crea utilizando API de la biblioteca OpenSSL. De forma predeterminada utilizamos API 3.0+
. Dado que OpenSSL 1.0.2
ya no es compatible, a partir de la versión NATS C Client v3.6.0
, la variable CMake NATS_BUILD_TLS_USE_OPENSSL_1_1_API
ahora está configurada en ON
de forma predeterminada (si está configurando un nuevo entorno) y utilizará las API de OpenSSL desde 1.1+
/ 3.0+
API. Aún podrá compilar con la biblioteca OpenSSL 1.0.2
configurando esta opción de CMake en OFF
:
cmake .. -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=OFF
La variable NATS_BUILD_TLS_USE_OPENSSL_1_1_API
está en desuso, lo que significa que en el futuro esta opción simplemente se eliminará y solo se utilizarán las API de OpenSSL 3.0+
. También se eliminará el código de la biblioteca que utiliza API OpenSSL más antiguas.
Tenga en cuenta que la variable NATS_BUILD_WITH_TLS_CLIENT_METHOD
que quedó obsoleta en v2.0.0
ahora se ha eliminado.
Dado que el cliente NATS C se vincula dinámicamente a la biblioteca OpenSSL, debe asegurarse de ejecutar su aplicación en una biblioteca OpenSSL 1.1+/3.0+.
Si desea vincularse a la biblioteca estática OpenSSL, debe eliminar CMakeCache.txt
y regenerarlo con la opción adicional:
rm CMakeCache.txt
cmake .. -DNATS_BUILD_OPENSSL_STATIC_LIBS=ON
Luego llame make
(o equivalente dependiendo de su plataforma) y esto debería garantizar que la biblioteca (y los ejemplos y/o el ejecutable del conjunto de pruebas) estén vinculados a la biblioteca OpenSSL, si CMake la encontró.
Al crear la biblioteca con soporte de Streaming, la biblioteca NATS utiliza la biblioteca libprotobuf-c. Cuando cmake se ejecuta por primera vez (o después de eliminar CMakeCache.txt
y llamar cmake ..
nuevamente), busca la biblioteca libprotobuf-c. Si no lo encuentra, se imprime un mensaje y el proceso de construcción falla. CMake busca la biblioteca en directorios donde normalmente se encuentran bibliotecas. Sin embargo, si desea especificar un directorio específico donde se encuentra la biblioteca, debe hacer esto:
cmake .. -DNATS_PROTOBUF_DIR=
La biblioteca estática se utilizará de forma predeterminada. Si desea cambiar eso, o si la biblioteca no tiene el nombre esperado, debe hacer esto:
# Use the library named mylibproto.so located at /my/location
cmake .. -DNATS_PROTOBUF_LIBRARY=/my/location/mylibproto.so
Los dos podrían combinarse si el encabezado de inclusión se encuentra en un directorio diferente
# 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
Si no desea crear las API de transmisión de NATS para incluirlas en la biblioteca de NATS:
cmake .. -DNATS_BUILD_STREAMING=OFF
Cuando se utilizan las nuevas funciones de seguridad NATS 2.0, la biblioteca necesita firmar algún "nonce" enviado por el servidor durante una conexión o reconexión. Usamos la firma de clave pública Ed25519. La biblioteca viene con algún código para realizar la firma. En la mayoría de los casos, estará bien, pero si el rendimiento es un problema (especialmente si planea usar mucho la función natsConnection_Sign()
), tendrá la opción de compilar con la biblioteca Libsodium.
Siga las instrucciones sobre cómo instalar la biblioteca libsodium aquí.
En macOS, puedes usar brew
:
brew install libsodium
En Linux, puedes usar apt-get
apt-get install libsodium-dev
Una vez instalado, puede reconstruir el cliente NATS C habilitando primero el uso de la biblioteca libsodium:
cmake .. -DNATS_BUILD_USE_SODIUM=ON
Si tiene la biblioteca libsodium instalada en una ubicación no estándar que CMake no puede encontrar, puede especificar la ubicación de este directorio:
cmake .. -DNATS_BUILD_USE_SODIUM=ON -DNATS_SODIUM_DIR=/my/path/to/libsodium
En plataformas donde valgrind
está disponible, puede ejecutar las pruebas con comprobaciones de memoria. Aquí hay un ejemplo:
make test ARGS="-T memcheck"
O puedes invocar directamente el programa ctest
:
ctest -T memcheck -V -I 1,4
El comando anterior ejecutaría las pruebas con valgrind
( -T memcheck
), con salida detallada ( -V
) y ejecutaría las pruebas del 1 al 4 ( -I 1,4
).
Si agrega una prueba a test/test.c
, debe agregarla al archivo list_test.txt
. Cada entrada contiene solo el nombre de la prueba, la función debe tener el mismo nombre, con un prefijo test_
. La lista está en orden alfabético, pero no es necesario, puedes agregarla en cualquier lugar.
Si está agregando un punto de referencia, debe agregarlo a list_bench.txt
. Estas pruebas están etiquetadas de manera diferente ( -L 'bench'
) y se ejecutan por separado en CI.
Debes volver a ejecutar cmake
para que los cambios surtan efecto:
cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ivan/nats.c/build
Puede utilizar las siguientes variables de entorno para influir en el comportamiento del conjunto de pruebas.
Cuando se ejecuta con verificación de memoria, el tiempo cambia y el rendimiento general es más lento. La siguiente variable permite al conjunto de pruebas ajustar algunos de los valores utilizados durante la prueba:
export NATS_TEST_VALGRIND=yes
En Windows, se set
en lugar de export
.
Al ejecutar las pruebas en modo detallado, la siguiente variable de entorno le permite ver la salida del servidor desde la propia prueba. Sin esta opción, la salida del servidor se silencia:
export NATS_TEST_KEEP_SERVER_OUTPUT=yes
Si desea cambiar el nombre ejecutable del servidor predeterminado ( nats-server.exe
) o especificar una ubicación específica, utilice esta variable de entorno:
set NATS_TEST_SERVER_EXE=c:testnats-server.exe
La API pública se ha documentado utilizando Doxygen.
Para generar la documentación, vaya al directorio doc
y escriba el siguiente comando:
doxygen DoxyFile.NATS.Client
Si alterna la compilación de las API de Streaming y la documentación ya no coincide con lo que se está compilando, puede actualizar la documentación cambiando el indicador de compilación NATS_UPDATE_DOC
y reconstruir la documentación.
Desde el directorio de compilación:
cmake .. -DNATS_UPDATE_DOC=ON
make
cd /doc
doxygen DoxyFile.NATS.Client
La documentación generada se ubicará en el directorio html
. Para ver la documentación, apunte su navegador al archivo index.html
en ese directorio.
Vaya aquí para obtener la documentación en línea.
El código fuente también está bastante documentado.
Esta sección enumera cambios importantes, como avisos de obsolescencia, etc.
2.0.0
Esta versión presenta los conceptos de seguridad utilizados por NATS Server 2.0.0
y, por lo tanto, se alinea con la versión del servidor. Se han introducido nuevas API, pero el cambio más importante es el nuevo comportamiento predeterminado con las conexiones TLS:
Al establecer una conexión segura, el nombre de host del certificado del servidor ahora siempre se verifica, independientemente de si el usuario ha invocado natsOptions_SetExpectedHostname()
. Esto puede dañar aplicaciones que, por ejemplo, usaban una IP para conectarse a un servidor que solo tenía el nombre de host en el certificado. Esto se puede resolver cambiando su aplicación para usar el nombre de host en la URL o haciendo uso de natsOptions_SetExpectedHostname()
. Si esto no es posible, puede restaurar el comportamiento anterior creando la biblioteca con el nuevo comportamiento deshabilitado. Consulte #tls-support para obtener más información.
Este repositorio solía incluir bibliotecas precompiladas de libprotobuf-c para macOS, Linux y Windows junto con los archivos de encabezado (en el directorio /pbuf
). Ahora hemos eliminado este directorio y requerimos que el usuario instale la biblioteca libprotobuf-c por separado. Consulte las instrucciones de construcción para especificar la ubicación de la biblioteca si CMake no puede encontrarla directamente.
1.8.0
natsConnStatus
tienen el prefijo NATS_CONN_STATUS_
. Si su aplicación no utiliza referencias a ningún valor original, como CONNECTED
o CLOSED
, etc., entonces no hay nada que deba hacer. Si lo haces, tienes dos opciones:NATS_BUILD_NO_PREFIX_CONNSTS
. Esto se puede hacer de esta manera desde el directorio de compilación: cmake .. -DNATS_BUILD_NO_PREFIX_CONNSTS=ON
El directorio de examples/getstarted
tiene un conjunto de ejemplos simples que son completamente funcionales, pero muy simples. El objetivo es demostrar lo fácil que es utilizar la API.
Un conjunto más complejo de ejemplos se encuentra en el directorio examples/
y también se puede utilizar para comparar la biblioteca del cliente.
Tenga en cuenta que, por simplicidad, aquí no se realiza la comprobación de errores.
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 );
}
La compatibilidad con JetStream comienza con la versión v3.0.0
de la biblioteca y el servidor NATS v2.2.0+
, aunque para obtener códigos de error específicos de JetStream se requiere el servidor con la versión v2.3.0+
. Algunas de las opciones de configuración solo están disponibles a partir de v2.3.3
, por lo que le recomendamos que utilice la última versión del servidor NATS para tener una mejor experiencia.
Mire los ejemplos denominados js-xxx.c
en el directorio de examples
para ver ejemplos sobre cómo utilizar la API. Los nuevos objetos y API están documentados completamente en la documentación en línea.
// 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 );
¡CARACTERÍSTICA EXPERIMENTAL! Nos reservamos el derecho de cambiar la API sin necesariamente cambiar la versión principal de la biblioteca.
Una tienda KeyValue es una vista materializada basada en JetStream. Un depósito es una secuencia y las claves son temas dentro de esa secuencia.
Algunas funciones requieren NATS Server v2.6.2
, por lo que le recomendamos que utilice la última versión de NATS Server para tener una mejor experiencia.
Los nuevos objetos y API están documentados completamente en la documentación en línea.
Ejemplo de cómo crear una tienda 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 );
Esto muestra cómo "vincularse" a uno existente:
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 );
Así es como se elimina un almacén KeyValue en el servidor:
jsCtx * js = NULL ;
// Assume we got a JetStream context in `js`...
s = js_DeleteKeyValue ( js , "KVS" );
Así es como poner un valor para una clave determinada:
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" );
Lo anterior coloca un valor para una clave determinada, pero si, en cambio, uno quiere asegurarse de que el valor se coloque para la clave solo si nunca antes existió, se llamaría:
// Same note than before: if "rev" is not needed, pass NULL:
s = kvStore_CreateString ( & rev , kv , "MY_KEY" , "my value" );
Se puede actualizar una clave si y sólo si la última revisión en el servidor coincide con la pasada a esta 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 );
Así es como se obtiene una clave:
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 );
Así es como se purga una clave:
kvStore * kv = NULL ;
// Assume we got a kvStore...
s = kvStore_Purge ( kv , "MY_KEY" );
Esto eliminará la clave en el servidor:
kvStore * kv = NULL ;
// Assume we got a kvStore...
s = kvStore_Delete ( kv , "MY_KEY" );
Para crear un "observador" para una clave determinada:
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 );
Para obtener el historial de una clave:
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 );
Así es como obtendrías las llaves de un cubo:
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 );
Los encabezados están disponibles cuando se conecta a servidores en la versión 2.2.0+.
Se parecen mucho a los encabezados http. Son un mapa de pares clave/valor, siendo el valor una matriz de cadenas.
Los encabezados permiten a los usuarios agregar metainformación sobre un mensaje sin interferir con la carga útil del mensaje.
Tenga en cuenta que si una aplicación intenta enviar un mensaje con un encabezado cuando está conectada a un servidor que no los comprende, la llamada de publicación devolverá el error NATS_NO_SERVER_SUPPORT
.
Existe una API para saber si el servidor actualmente conectado admite encabezados:
natsStatus s = natsConnection_HasHeaderSupport ( conn );
if ( s == NATS_NO_SERVER_SUPPORT )
// deal with server not supporting this feature.
Si el servidor entiende los encabezados pero está a punto de entregar el mensaje a un cliente que no los entiende, los encabezados se eliminan para que los clientes más antiguos aún puedan recibir el mensaje. Es importante tener todos los clientes y servidores en una versión que admita encabezados si las aplicaciones dependen de encabezados.
Para obtener más detalles sobre la API de encabezados, obtenga el ejemplo: examples/getstarted/headers.c
.
El comodín *
coincide con cualquier token, en cualquier nivel del tema:
natsConnection_Subscribe ( & sub , nc , "foo.*.baz" , onMsg , NULL );
Este suscriptor recibiría mensajes enviados a:
Sin embargo, no recibirá mensajes sobre:
El comodín >
coincide con cualquier duración del suspenso de un tema y solo puede ser el último token.
natsConnection_Subscribe ( & sub , nc , "foo.>" , onMsg , NULL );
Este suscriptor recibiría cualquier mensaje enviado a:
Sin embargo, no recibiría mensajes enviados a:
Publicar sobre este tema haría que los dos suscriptores anteriores recibieran el mensaje:
natsConnection_PublishString ( nc , "foo.bar.baz" , "got it?" );
Todas las suscripciones con el mismo nombre de cola formarán un grupo de cola. Cada mensaje se entregará a un solo suscriptor por grupo de cola, utilizando la semática de cola. Puede tener tantos grupos de cola como desee. Los suscriptores normales seguirán funcionando como se esperaba.
natsConnection_QueueSubscribe ( & sub , nc , "foo" , "job_workers" , onMsg , NULL );
(Tenga en cuenta que la biblioteca debe compilarse con soporte TLS, que es el predeterminado, para que estas API funcionen. Consulte el capítulo sobre compilación sobre cómo compilar con o sin TLS para obtener más detalles).
Una conexión SSL/TLS se configura mediante el uso de natsOptions
. Dependiendo del nivel de seguridad que desee, puede ser tan simple como establecer el valor booleano seguro en verdadero en la llamada natsOptions_SetSecure()
.
Incluso con seguridad total (el cliente verifica el certificado del servidor y el servidor requiere certificados de cliente), la configuración implica solo unas pocas llamadas.
// 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!