AC-Client für das NATS-Nachrichtensystem.
Hier finden Sie die Online-Dokumentation und die häufig gestellten Fragen.
Diese NATS-Client-Implementierung basiert stark auf dem NATS GO-Client. Es gibt Unterstützung für Mac OS/X, Linux und Windows (obwohl wir keine spezifische Plattform-Unterstützungsmatrix haben).
Es stehen mehrere Paketmanager mit NATS-C-Client-Bibliothek zur Verfügung. Wenn Sie eines kennen, das nicht in dieser Liste enthalten ist, senden Sie bitte eine PR, um es hinzuzufügen!
Laden Sie zunächst den Quellcode herunter:
git clone [email protected]:nats-io/nats.c.git .
Verwenden Sie zum Erstellen der Bibliothek CMake. Beachten Sie, dass die NATS-Streaming-API standardmäßig erstellt und in die NATS-Bibliothek aufgenommen wird. Lesen Sie weiter unten, wenn Sie die Streaming-bezogenen APIs nicht erstellen möchten.
Stellen Sie sicher, dass CMake zu Ihrem Pfad hinzugefügt wird. Wenn Sie unter Windows erstellen, öffnen Sie eine Befehlsshell aus dem Visual Studio-Menü „Extras“ und wählen Sie die entsprechende Befehlsshell aus (x64 oder x86 für 64- bzw. 32-Bit-Builds). Sie müssen dies wahrscheinlich auch mit Administratorrechten ausführen.
Erstellen Sie ein build
-Verzeichnis (jeder Name würde funktionieren) aus dem Stammquellbaum und cd
hinein. Geben Sie dann zum ersten Mal diesen Befehl aus:
cmake ..
In einigen Architekturen kann es zu einem Kompilierungsfehler für mutex.co
kommen, da es keine Unterstützung für die Assembler-Anweisung gibt, die wir verwenden, um nachzugeben, wenn wir versuchen, eine Sperre zu erhalten.
Möglicherweise erhalten Sie diese Art von Build-Fehler:
/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
Wenn das der Fall ist, können Sie das Problem lösen, indem Sie das NATS_BUILD_NO_SPIN
-Flag aktivieren (oder -DNATS_NO_SPIN
verwenden, wenn Sie ohne CMake kompilieren):
cmake .. -DNATS_BUILD_NO_SPIN=ON
Wenn Sie die Bibliothek zuvor erstellt haben, müssen Sie möglicherweise einen make clean
durchführen oder einfach das Build-Verzeichnis löschen und neu erstellen, bevor Sie den Befehl cmake ausführen.
Um unter Windows zu erstellen, müssen Sie den Build-Generator auswählen. Um beispielsweise nmake
auszuwählen, würden Sie Folgendes ausführen:
cmake .. -G "NMake Makefiles"
Wenn Sie cmake -h
ausführen, erhalten Sie eine Liste möglicher Optionen und alle Generatornamen.
Alternativ können Sie die GUI-Version ausführen. Starten Sie von derselben Build -Befehlsshell aus die GUI:
c:program files (x86)CMakebincmake-gui.exe
Wenn Sie mit einem leeren Build-Verzeichnis begonnen haben, müssen Sie die Quelle und das Build-Verzeichnis auswählen und dann auf Configure
klicken. Hier können Sie aus dem Dropdown-Feld den Namen des Build-Generators auswählen. Wenn Sie fertig sind, klicken Sie auf Generate
. Anschließend können Sie zu Ihrer Befehlsshell oder zu Visual Studio zurückkehren und den Build erstellen.
Um einige der Build-Optionen zu ändern, müssen Sie den Cache bearbeiten und neu erstellen.
make edit_cache
Beachten Sie, dass Sie, wenn Sie unter Windows bauen und „NMake Makefiles“ ausgewählt haben, alle folgenden Referenzen durch make
nmake
ersetzen.
Durch Bearbeiten des Caches können Sie den Build-Typ (Debug, Release usw.), die Architektur (64 oder 32 Bit) usw. auswählen.
Das Standardziel erstellt alles, also die statischen und gemeinsam genutzten NATS-Bibliotheken sowie die Beispiele und das Testprogramm. Sie befinden sich jeweils in ihren jeweiligen Verzeichnissen unter Ihrem Build-Verzeichnis: src
, examples
und test
.
make install
Kopiert sowohl die statischen als auch die gemeinsam genutzten Bibliotheken im Ordner install/lib
und die öffentlichen Header in install/include
.
Standardmäßig wird die Bibliothek mit TLS-Unterstützung erstellt. Sie können dies über die cmake-GUI make edit_cache
deaktivieren und die Option NATS_BUILD_WITH_TLS
auf OFF
setzen oder die Option direkt an den cmake
-Befehl übergeben:
cmake .. -DNATS_BUILD_WITH_TLS=OFF
Ab 2.0.0
wird beim Erstellen mit TLS/SSL-Unterstützung immer der erwartete Hostname des Serverzertifikats überprüft. Dies bedeutet, dass der in den URLs oder über die Option natsOptions_SetExpectedHostname()
angegebene Hostname zur Überprüfung des im Zertifikat vorhandenen Hostnamens verwendet wird. Vor 2.0.0
wurde der Hostname nur überprüft, wenn die Option natsOptions_SetExpectedHostname()
aufgerufen wurde.
Obwohl wir empfehlen, das neue Standardverhalten beizubehalten, können Sie das vorherige Verhalten wiederherstellen, indem Sie die Bibliothek mit deaktivierter Option erstellen:
cmake .. -DNATS_BUILD_TLS_FORCE_HOST_VERIFY=OFF
Der NATS-C-Client wird mithilfe von APIs aus der OpenSSL-Bibliothek erstellt. Standardmäßig verwenden wir APIs 3.0+
. Da OpenSSL 1.0.2
ab der Version NATS C Client v3.6.0
nicht mehr unterstützt wird, ist die CMake-Variable NATS_BUILD_TLS_USE_OPENSSL_1_1_API
jetzt standardmäßig auf ON
gesetzt (wenn Sie eine neue Umgebung einrichten) und verwendet OpenSSL-APIs ab 1.1+
. 3.0+
APIs. Sie können weiterhin mit der OpenSSL 1.0.2
-Bibliothek kompilieren, indem Sie diese CMake-Option auf OFF
setzen:
cmake .. -DNATS_BUILD_TLS_USE_OPENSSL_1_1_API=OFF
Die Variable NATS_BUILD_TLS_USE_OPENSSL_1_1_API
ist veraltet, was bedeutet, dass diese Option in Zukunft einfach entfernt wird und nur noch OpenSSL 3.0+
APIs verwendet werden. Der Code in der Bibliothek, der ältere OpenSSL-APIs verwendet, wird ebenfalls entfernt.
Beachten Sie, dass die Variable NATS_BUILD_WITH_TLS_CLIENT_METHOD
, die in v2.0.0
veraltet war, jetzt entfernt wurde.
Da der NATS C-Client dynamisch eine Verbindung zur OpenSSL-Bibliothek herstellt, müssen Sie sicherstellen, dass Sie Ihre Anwendung dann mit einer OpenSSL 1.1+/3.0+-Bibliothek ausführen.
Wenn Sie eine Verknüpfung zur statischen OpenSSL-Bibliothek herstellen möchten, müssen Sie die CMakeCache.txt
löschen und mit der zusätzlichen Option neu generieren:
rm CMakeCache.txt
cmake .. -DNATS_BUILD_OPENSSL_STATIC_LIBS=ON
Rufen Sie dann make
(oder ein Äquivalent, abhängig von Ihrer Plattform) auf und dies sollte sicherstellen, dass die Bibliothek (und Beispiele und/oder ausführbare Testsuite-Dateien) mit der OpenSSL-Bibliothek verknüpft sind, wenn sie von CMake gefunden wurde.
Beim Erstellen der Bibliothek mit Streaming-Unterstützung verwendet die NATS-Bibliothek die Bibliothek libprotobuf-c. Wenn cmake zum ersten Mal ausgeführt wird (oder nachdem CMakeCache.txt
entfernt und cmake ..
erneut aufgerufen wurde), sucht es nach der Bibliothek libprotobuf-c. Wenn es nicht gefunden wird, wird eine Meldung ausgegeben und der Erstellungsprozess schlägt fehl. CMake sucht in Verzeichnissen nach der Bibliothek, in denen normalerweise Bibliotheken zu finden sind. Wenn Sie jedoch ein bestimmtes Verzeichnis angeben möchten, in dem sich die Bibliothek befindet, müssen Sie Folgendes tun:
cmake .. -DNATS_PROTOBUF_DIR=
Standardmäßig wird die statische Bibliothek verwendet. Wenn Sie das ändern möchten oder die Bibliothek nicht den erwarteten Namen hat, müssen Sie Folgendes tun:
# Use the library named mylibproto.so located at /my/location
cmake .. -DNATS_PROTOBUF_LIBRARY=/my/location/mylibproto.so
Die beiden könnten kombiniert werden, wenn sich der Include-Header in einem anderen Verzeichnis befindet
# 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
Wenn Sie die NATS-Streaming-APIs nicht erstellen möchten, um sie in die NATS-Bibliothek aufzunehmen:
cmake .. -DNATS_BUILD_STREAMING=OFF
Bei Verwendung der neuen NATS 2.0-Sicherheitsfunktionen muss die Bibliothek eine „Nonce“ signieren, die vom Server während einer Verbindung oder erneuten Verbindung gesendet wird. Wir verwenden die Public-Key-Signatur Ed25519. Die Bibliothek enthält Code zum Durchführen der Signatur. In den meisten Fällen wird es in Ordnung sein, aber wenn die Leistung ein Problem darstellt (insbesondere, wenn Sie die Funktion natsConnection_Sign()
häufig verwenden möchten), haben Sie die Möglichkeit, mit der Libsodium-Bibliothek zu erstellen.
Befolgen Sie hier die Anweisungen zur Installation der libsodium-Bibliothek.
Unter macOS können Sie brew
verwenden:
brew install libsodium
Unter Linux können Sie apt-get
verwenden
apt-get install libsodium-dev
Nach der Installation können Sie den NATS C-Client neu erstellen, indem Sie zunächst die Verwendung der libsodium-Bibliothek aktivieren:
cmake .. -DNATS_BUILD_USE_SODIUM=ON
Wenn Sie die libsodium-Bibliothek an einem nicht standardmäßigen Speicherort installiert haben, den CMake nicht finden kann, können Sie den Speicherort dieses Verzeichnisses angeben:
cmake .. -DNATS_BUILD_USE_SODIUM=ON -DNATS_SODIUM_DIR=/my/path/to/libsodium
Auf Plattformen, auf denen valgrind
verfügbar ist, können Sie die Tests mit Speicherprüfungen ausführen. Hier ist ein Beispiel:
make test ARGS="-T memcheck"
Oder Sie können das ctest
-Programm direkt aufrufen:
ctest -T memcheck -V -I 1,4
Der obige Befehl würde die Tests mit valgrind
( -T memcheck
), mit ausführlicher Ausgabe ( -V
) und den Tests von 1 bis 4 ( -I 1,4
) ausführen.
Wenn Sie einen Test zu test/test.c
hinzufügen, müssen Sie ihn in die Datei list_test.txt
einfügen. Jeder Eintrag enthält nur den Testnamen, die Funktion muss identisch benannt sein, mit einem test_
Präfix. Die Liste ist alphabetisch geordnet, muss aber nicht sein, sie kann überall hinzugefügt werden.
Wenn Sie einen Benchmark hinzufügen, sollte dieser zur list_bench.txt
hinzugefügt werden. Diese Tests sind unterschiedlich gekennzeichnet ( -L 'bench'
) und werden separat auf CI ausgeführt.
Sie müssen cmake
erneut ausführen, damit die Änderungen wirksam werden:
cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ivan/nats.c/build
Sie können die folgenden Umgebungsvariablen verwenden, um das Verhalten der Testsuite zu beeinflussen.
Bei der Ausführung mit Speicherprüfung kommt es zu zeitlichen Änderungen und die Gesamtleistung ist langsamer. Mit der folgenden Variablen kann die Testsuite einige der während des Tests verwendeten Werte anpassen:
export NATS_TEST_VALGRIND=yes
Unter Windows würde es anstelle von export
set
werden.
Wenn Sie die Tests im ausführlichen Modus ausführen, können Sie mit der folgenden Umgebungsvariablen die Serverausgabe im Test selbst sehen. Ohne diese Option wird die Serverausgabe stummgeschaltet:
export NATS_TEST_KEEP_SERVER_OUTPUT=yes
Wenn Sie den Standardnamen der ausführbaren Serverdatei ( nats-server.exe
) ändern oder einen bestimmten Speicherort angeben möchten, verwenden Sie diese Umgebungsvariable:
set NATS_TEST_SERVER_EXE=c:testnats-server.exe
Die öffentliche API wurde mit Doxygen dokumentiert.
Um die Dokumentation zu generieren, gehen Sie in das doc
und geben Sie den folgenden Befehl ein:
doxygen DoxyFile.NATS.Client
Wenn Sie den Build der Streaming-APIs umschalten und die Dokumentation nicht mehr mit dem übereinstimmt, was gerade erstellt wird, können Sie die Dokumentation aktualisieren, indem Sie das Build-Flag NATS_UPDATE_DOC
ändern und die Dokumentation neu erstellen.
Aus dem Build-Verzeichnis:
cmake .. -DNATS_UPDATE_DOC=ON
make
cd /doc
doxygen DoxyFile.NATS.Client
Die generierte Dokumentation befindet sich im html
Verzeichnis. Um die Dokumentation anzuzeigen, richten Sie Ihren Browser auf die Datei index.html
in diesem Verzeichnis.
Hier finden Sie die Online-Dokumentation.
Der Quellcode ist ebenfalls gut dokumentiert.
In diesem Abschnitt werden wichtige Änderungen wie Einstellungshinweise usw. aufgeführt.
2.0.0
Diese Version stellt die von NATS Server 2.0.0
verwendeten Sicherheitskonzepte vor und stimmt daher mit der Serverversion überein. Es wurden neue APIs eingeführt, aber die wichtigste Änderung ist das neue Standardverhalten bei TLS-Verbindungen:
Beim Aufbau einer sicheren Verbindung wird der Hostname des Serverzertifikats jetzt immer überprüft, unabhängig davon, ob der Benutzer natsOptions_SetExpectedHostname()
aufgerufen hat. Dies kann Anwendungen beschädigen, die beispielsweise eine IP-Adresse für die Verbindung zu einem Server verwendeten, der nur den Hostnamen im Zertifikat enthielt. Dies kann gelöst werden, indem Sie Ihre Anwendung so ändern, dass sie den Hostnamen in der URL verwendet, oder indem Sie natsOptions_SetExpectedHostname()
verwenden. Wenn dies nicht möglich ist, können Sie das alte Verhalten wiederherstellen, indem Sie die Bibliothek mit deaktiviertem neuen Verhalten erstellen. Weitere Informationen finden Sie unter #tls-support.
Dieses Repository enthielt früher vorkompilierte Bibliotheken von libprotobuf-c für macOS, Linux und Windows zusammen mit den Header-Dateien (im Verzeichnis /pbuf
). Wir haben dieses Verzeichnis nun entfernt und verlangen, dass der Benutzer die Bibliothek libprotobuf-c separat installiert. Sehen Sie sich die Bauanweisungen an, um den Speicherort der Bibliothek anzugeben, wenn CMake ihn nicht direkt finden kann.
1.8.0
natsConnStatus
-Enumerationswerten wurde NATS_CONN_STATUS_
vorangestellt. Wenn Ihre Anwendung keine Referenzierung auf einen Originalwert wie CONNECTED
oder CLOSED
usw. verwendet, müssen Sie nichts tun. Wenn Sie dies tun, haben Sie zwei Möglichkeiten:NATS_BUILD_NO_PREFIX_CONNSTS
. Dies kann auf diese Weise vom Build-Verzeichnis aus erfolgen: cmake .. -DNATS_BUILD_NO_PREFIX_CONNSTS=ON
Das Verzeichnis examples/getstarted
enthält eine Reihe einfacher Beispiele, die voll funktionsfähig und dennoch sehr einfach sind. Ziel ist es zu demonstrieren, wie einfach die Verwendung der API ist.
Ein komplexerer Satz von Beispielen befindet sich im Verzeichnis examples/
und kann auch zum Benchmarking der Client-Bibliothek verwendet werden.
Beachten Sie, dass der Einfachheit halber hier keine Fehlerprüfung durchgeführt wird.
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 );
}
Die Unterstützung für JetStream beginnt mit der Version v3.0.0
der Bibliothek und dem NATS-Server v2.2.0+
, obwohl für den Erhalt von JetStream-spezifischen Fehlercodes der Server in der Version v2.3.0+
erforderlich ist. Einige der Konfigurationsoptionen sind erst ab v2.3.3
verfügbar. Wir empfehlen Ihnen daher, die neueste NATS-Server-Version zu verwenden, um ein besseres Erlebnis zu erzielen.
Sehen Sie sich Beispiele mit dem Namen js-xxx.c
im examples
an, um Beispiele für die Verwendung der API zu finden. Die neuen Objekte und APIs sind vollständig in der Online-Dokumentation dokumentiert.
// 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 );
EXPERIMENTELLES FUNKTION! Wir behalten uns das Recht vor, die API zu ändern, ohne unbedingt die Hauptversion der Bibliothek zu ändern.
Ein KeyValue-Store ist eine materialisierte Ansicht, die auf JetStream basiert. Ein Bucket ist ein Stream und Schlüssel sind Subjekte innerhalb dieses Streams.
Für einige Funktionen ist NATS Server v2.6.2
erforderlich. Wir empfehlen Ihnen daher, die neueste NATS-Server-Version zu verwenden, um ein besseres Erlebnis zu erzielen.
Die neuen Objekte und APIs sind vollständig in der Online-Dokumentation dokumentiert.
Beispiel für die Erstellung eines KeyValue-Speichers:
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 );
Dies zeigt, wie man eine „Bindung“ an eine bestehende durchführt:
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 );
So löschen Sie einen KeyValue-Speicher auf dem Server:
jsCtx * js = NULL ;
// Assume we got a JetStream context in `js`...
s = js_DeleteKeyValue ( js , "KVS" );
So geben Sie einen Wert für einen bestimmten Schlüssel ein:
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" );
Das Obige platziert einen Wert für einen bestimmten Schlüssel, aber wenn man stattdessen sicherstellen möchte, dass der Wert nur für den Schlüssel platziert wird, wenn er noch nie zuvor existiert hat, würde man Folgendes aufrufen:
// Same note than before: if "rev" is not needed, pass NULL:
s = kvStore_CreateString ( & rev , kv , "MY_KEY" , "my value" );
Man kann einen Schlüssel genau dann aktualisieren, wenn die letzte Revision auf dem Server mit der an diese API übergebenen übereinstimmt:
// 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 );
So erhalten Sie einen Schlüssel:
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 );
So löschen Sie einen Schlüssel:
kvStore * kv = NULL ;
// Assume we got a kvStore...
s = kvStore_Purge ( kv , "MY_KEY" );
Dadurch wird der Schlüssel auf dem Server gelöscht:
kvStore * kv = NULL ;
// Assume we got a kvStore...
s = kvStore_Delete ( kv , "MY_KEY" );
So erstellen Sie einen „Watcher“ für einen bestimmten Schlüssel:
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 );
So erhalten Sie den Verlauf eines Schlüssels:
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 );
So erhalten Sie die Schlüssel zu einem Eimer:
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 );
Header sind verfügbar, wenn eine Verbindung zu Servern ab Version 2.2.0 hergestellt wird.
Sie ähneln stark HTTP-Headern. Sie sind eine Zuordnung von Schlüssel/Wert-Paaren, wobei der Wert ein Array von Zeichenfolgen ist.
Mit Headern können Benutzer Metainformationen zu einer Nachricht hinzufügen, ohne die Nutzlast der Nachricht zu beeinträchtigen.
Beachten Sie, dass der Veröffentlichungsaufruf den Fehler NATS_NO_SERVER_SUPPORT
zurückgibt, wenn eine Anwendung versucht, eine Nachricht mit einem Header zu senden, während sie mit einem Server verbunden ist, der diese nicht versteht.
Es gibt eine API, um festzustellen, ob der aktuell verbundene Server Header unterstützt:
natsStatus s = natsConnection_HasHeaderSupport ( conn );
if ( s == NATS_NO_SERVER_SUPPORT )
// deal with server not supporting this feature.
Wenn der Server Header versteht, die Nachricht aber an einen Client übermitteln möchte, der dies nicht versteht, werden die Header entfernt, sodass die älteren Clients die Nachricht weiterhin empfangen können. Es ist wichtig, dass alle Clients und Server eine Version haben, die Header unterstützt, wenn Anwendungen auf Header angewiesen sind.
Weitere Informationen zur Header-API finden Sie im Beispiel: examples/getstarted/headers.c
.
Der Platzhalter *
entspricht jedem Token auf jeder Ebene des Betreffs:
natsConnection_Subscribe ( & sub , nc , "foo.*.baz" , onMsg , NULL );
Dieser Abonnent würde Nachrichten erhalten, die an Folgendes gesendet wurden:
Es werden jedoch keine Nachrichten empfangen über:
Der Platzhalter >
entspricht einer beliebigen Länge des Fehlers eines Subjekts und kann nur das letzte Token sein.
natsConnection_Subscribe ( & sub , nc , "foo.>" , onMsg , NULL );
Dieser Abonnent würde jede Nachricht erhalten, die an Folgendes gesendet wird:
Es würden jedoch keine Nachrichten empfangen, die gesendet wurden an:
Eine Veröffentlichung zu diesem Thema würde dazu führen, dass die beiden oben genannten Abonnenten die Nachricht erhalten:
natsConnection_PublishString ( nc , "foo.bar.baz" , "got it?" );
Alle Abonnements mit demselben Warteschlangennamen bilden eine Warteschlangengruppe. Jede Nachricht wird mithilfe der Warteschlangensematik nur an einen Abonnenten pro Warteschlangengruppe zugestellt. Sie können beliebig viele Warteschlangengruppen haben. Normale Abonnenten funktionieren weiterhin wie erwartet.
natsConnection_QueueSubscribe ( & sub , nc , "foo" , "job_workers" , onMsg , NULL );
(Beachten Sie, dass die Bibliothek mit TLS-Unterstützung erstellt werden muss – was standardmäßig der Fall ist – damit diese APIs funktionieren. Weitere Informationen zum Erstellen mit oder ohne TLS finden Sie im Kapitel „Erstellen“.)
Eine SSL/TLS-Verbindung wird mithilfe von natsOptions
konfiguriert. Abhängig von der gewünschten Sicherheitsstufe kann es so einfach sein, den sicheren booleschen Wert beim Aufruf natsOptions_SetSecure()
auf „true“ zu setzen.
Selbst bei voller Sicherheit (Client überprüft Serverzertifikat und Server benötigt Clientzertifikate) erfordert die Einrichtung nur wenige Aufrufe.
// 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!