Protocole de stockage d’état
Le stockage d’état est un système de stockage distribué au sein du cluster Opérations Azure IoT. Le magasin d’états offre les mêmes garanties de haute disponibilité que les messages MQTT dans l’agent MQTT. Conformément aux lignes directrices du protocole MQTT5/RPC, les clients doivent utiliser MQTT5 pour interagir avec le stockage d’état. Cet article fournit des conseils sur le protocole aux développeurs qui ont besoin d’implémenter leurs propres clients de stockage d’état.
Vue d’ensemble
Le stockage d’état prend en charge les commandes suivantes :
SET
<keyName><keyValue><setOptions>GET
<keyName>DEL
<keyName>VDEL
<keyName><keyValue> ## Supprime un nom de <keyName> si et uniquement si sa valeur est <keyValue>
Le protocole utilise le modèle requête-réponse suivant :
- Requête. Les clients publient une requête auprès d'une rubrique bien définie du système de stockage d'informations. Pour publier la requête, les clients utilisent les propriétés requises et les données utiles décrites dans les sections suivantes.
- Response. Le magasin d'état traite la requête de manière asynchrone et répond sur le thème de réponse initialement fourni par le client.
Le diagramme suivant montre la vue de base de la requête et de la réponse :
Sujet du système de stockage d'état, QoS et propriétés MQTT5 requises
Pour communiquer avec le magasin d'État, les clients doivent remplir les conditions suivantes :
- Utilisez MQTT5. Pour en savoir plus, consultez la spécification MQTT 5.
- Utilisez QoS 1 (qualité de niveau de service 1). QoS 1 est décrit dans la spécification MQTT 5.
- Avoir une horloge qui est à moins d'une minute de l'horloge du courtier MQTT.
Pour communiquer avec le magasin d’états, les clients doivent demander PUBLISH
à la rubrique système statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
. Étant donné que le magasin d’états fait partie d'Azure IoT Operations, il effectue un SUBSCRIBE
implicite à cette rubrique au démarrage.
Pour construire une requête, les propriétés MQTT5 suivantes sont nécessaires. Si ces propriétés ne sont pas présentes ou si la requête n'est pas de type QoS 1, la requête échoue.
- Rubrique de réponse. Le magasin d'état répond à la requête initiale en utilisant cette valeur. En guise de meilleure pratique, mettez en forme la rubrique de réponse en tant que
clients/{clientId}/services/statestore/_any_/command/invoke/response
. La définition de la rubrique de réponse commestatestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
ou qui commence parclients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8
n’est pas autorisée sur une demande de magasin d’états. Le magasin d’états déconnecte les clients MQTT qui utilisent une rubrique de réponse non valide. - Données de corrélation. Lorsque le magasin d'état envoie une réponse, il inclut les données de corrélation de la requête initiale.
Le diagramme suivant montre une vue développée de la requête et de la réponse :
Commandes prises en charge
Les commandes SET
, GET
et DEL
se comportent comme prévu.
Les valeurs que la commande SET
définit et que la commande GET
récupère sont des données binaires arbitraires. La taille des valeurs n’est limitée que par la taille maximale de la charge utile MQTT et par les limitations de ressources de l’Agent MQTT et du client.
SET
options
La commande SET
fournit des indicateurs facultatifs au-delà des indicateurs de base keyValue
et keyName
:
NX
. Permet de définir la clé uniquement si elle n'existe pas déjà.NEX <value>
. Autorise la définition de la clé uniquement si la clé n’existe pas ou si la valeur de la clé est déjà définie sur la <valeur>. L’indicateurNEX
est généralement utilisé pour un client renouvelant l’expiration (PX
) sur une clé.PX
. Durée pendant laquelle la clé doit persister avant d'expirer, en millisecondes.
VDEL
options
La commande VDEL
est un cas spécial de la commande DEL
. DEL
supprime inconditionnellement le keyName
donné. VDEL
nécessite un autre argument appelé keyValue
. VDEL
supprime uniquement le keyName
donné s’il a le même keyValue
.
Format de charge utile
Le format de charge utile PUBLISH
du magasin d’états est inspiré de RESP3, qui est le protocole sous-jacent utilisé par Redis. RESP3 encode à la fois le verbe, tel que SET
ou GET
, et les paramètres tels que keyName
et keyValue
.
Respect de la casse
Le client doit envoyer les verbes et les options en majuscules.
Format de la demande
Les demandes sont formatées comme dans l'exemple suivant. Après RESP3, *
représente le nombre d’éléments d’un tableau. Le caractère $
est le nombre de caractères de la ligne suivante, à l’exclusion du CRLF de fin.
Les commandes prises en charge au format RESP3 sont GET
, SET
, DEL
et VDEL
.
*{NUMBER-OF-ARGUMENTS}<CR><LF>
${LENGTH-OF-NEXT-LINE}<CR><LF>
{COMMAND-NAME}<CR><LF>
${LENGTH-OF-NEXT-LINE}<CR><LF> // This is always the keyName with the current supported verbs.
{KEY-NAME}<CR><LF>
// Next lines included only if command has additional arguments
${LENGTH-OF-NEXT-LINE}<CR><LF> // This is always the keyValue for set
{KEY-VALUE}<CR><LF>
L'exemple suivant montre les charges utiles RESP3 du magasin d'état :
*3<CR><LF>$3<CR><LF>set<CR><LF>$7<CR><LF>SETKEY2<CR><LF>$6<CR><LF>VALUE5<CR><LF>
*2<CR><LF>$3<CR><LF>get<CR><LF>$7<CR><LF>SETKEY2<CR><LF>
*2<CR><LF>$3<CR><LF>del<CR><LF>$7<CR><LF>SETKEY2<CR><LF>
*3<CR><LF>$4<CR><LF>vdel<CR><LF>$7<CR><LF>SETKEY2<CR><LF>$3<CR><LF>ABC<CR><LF>
Remarque
Notez que SET
nécessite des propriétés MQTT5 supplémentaires, comme expliqué dans la section Contrôle de version et horloges logiques hybrides.
Format de la réponse
Lorsque le magasin d’états détecte une charge utile RESP3 non valide, il retourne toujours une réponse à Response Topic
du demandeur. Parmi les exemples de charges utiles non valides, on peut citer une commande non valide, un RESP3 illégal ou un dépassement d'entier. Une charge utile non valide commence par la chaîne -ERR
et contient plus de détails.
Remarque
Une requête GET
, DEL
ou VDEL
sur une clé inexistante n’est pas considérée comme une erreur.
Si un client envoie une charge utile non valide, le magasin d'état envoie une charge utile comme dans l'exemple suivant :
-ERR syntax error
Réponse de SET
Lorsqu’une requête SET
réussit, le magasin d’états retourne la charge utile suivante :
+OK<CR><LF>
Si une requête SET échoue, car une vérification de condition telle qu’elle est spécifiée dans les options de jeu NX ou NEX qui signifie que la clé ne peut pas être définie, le magasin d’états retourne la charge utile suivante :
-1<CR><LF>
Réponse de GET
Lorsqu’une requête GET
est effectuée sur une clé inexistante, le magasin d’états retourne la charge utile suivante :
$-1<CR><LF>
Lorsque la clé est trouvée, le magasin d'état renvoie la valeur dans le format suivant :
${NumberOfBytes}<CR><LF>
{KEY-VALUE}
La sortie du magasin d’états qui retourne la valeur 1234
ressemble à l’exemple suivant :
$4<CR><LF>1234<CR><LF>
Réponse DEL
et VDEL
Le magasin d'état renvoie le nombre de valeurs qu'il supprime lors d'une requête de suppression. Actuellement, le magasin d'état ne peut supprimer qu'une seule valeur à la fois.
:{NumberOfDeletes}<CR><LF> // Will be 1 on successful delete or 0 if the keyName is not present
Voici un exemple de résultat d’une commande DEL
réussie :
:1<CR><LF>
Si une requête VDEL échoue, car la valeur spécifiée ne correspond pas à la valeur associée à la clé, le magasin d’états retourne la charge utile suivante :
-1<CR><LF>
-ERR
réponses
Voici la liste actuelle des chaînes d’erreur. Votre application cliente doit gérer erreur inconnue chaînes pour prendre en charge les mises à jour du magasin d’états.
Chaîne d’erreur retournée à partir du magasin d’états | Explication |
---|---|
le timestamp demandé est trop loin dans le temps. Vérifiez que les horloges système broker et client sont synchronisées | Un timestamp demandé inattendu a été provoqué par le magasin d’état et les horloges clientes ne sont pas synchronisées. |
un jeton d’authentification est requis pour cette requête | Désolé, une erreur se produit si une clé est marquée avec un jeton d’escrime, mais que le client ne spécifie pas le jeton d’escrime. |
le timestamp du jeton de clôture demandé est trop éloigné dans le temps. Vérifiez que les horloges système broker et client sont synchronisées | Horodatage inattendu du jeton de clôture causé par la désynchronisation des horloges du magasin d’état et du client. |
le jeton de clôture demandé est une version inférieure au jeton de clôture protégeant la ressource | Version incorrecte du jeton de clôture demandé. Pour plus d’informations, consultez [Horloges logiques de contrôle de version et hybrides]. (horloges logiques #versioning et hybrides) |
le quota a été dépassé | Le magasin d’états a un quota du nombre de clés qu’il peut stocker, qui est basé sur le profil de mémoire du répartiteur MQTT spécifié. |
erreur de syntaxe | La charge utile envoyée n’est pas conforme à la définition du magasin d’états. |
non autorisé | Erreur d’autorisation |
commande inconnue | La commande n’est pas reconnue. |
nombre d’arguments erroné | Nombre incorrect d’arguments attendus. |
horodatage manquant | Lorsque les clients effectuent un SET, ils doivent définir la propriété utilisateur MQTT5 __ts comme un HLC représentant son horodatage. |
horodatage mal formé | L’horodatage dans le __ts ou le jeton d’escrime n’est pas légal. |
la longueur de la clé est égale à zéro | Les clés ne peuvent pas être de longueur nulle dans le magasin d’états. |
Versioning et horloges logiques hybrides
Cette section décrit comment le magasin d'états gère les versions.
Versions en tant qu’horloges logiques hybrides
Le magasin d'état conserve une version pour chaque valeur qu'il stocke. Le magasin d'état pourrait utiliser un compteur à augmentation monotone pour conserver les versions. Au lieu de cela, le magasin d'état utilise une horloge logique hybride (HLC) pour représenter les versions. Pour plus d’informations, consultez les articles sur la conception originale des HLC et l’intention derrière les HLC.
Le magasin d'État utilise le format suivant pour définir les HLC :
{wallClock}:{counter}:{node-Id}
Le wallClock
est le nombre de millisecondes depuis l’époque Unix. counter
et node-Id
fonctionnent en tant que HLC en général.
Lorsque les clients effectuent un SET
, ils doivent définir la propriété utilisateur MQTT5 __ts
comme un HLC représentant son timestamp, en fonction de l’horloge actuelle du client. Le magasin d'état renvoie la version de la valeur dans son message de réponse. La réponse est également spécifiée en tant que HLC et utilise également la propriété utilisateur __ts
MQTT5. Le HLC renvoyé est toujours supérieur au HLC de la requête initiale.
Exemple de définition et de récupération de la version d'une valeur
Cette section présente un exemple de définition et d'obtention de la version d'une valeur.
Un client définit keyName=value
. L'horloge du client est le 3 octobre à 23 h 07 : 05 GMT. La valeur de l’horloge est 1696374425000
milliseconde depuis l’époque Unix. Supposons que l'horloge du système du magasin d'état soit identique à celle du système du client. Le client effectue la commande SET
comme décrit précédemment.
Le diagramme suivant illustre la commande SET
:
La propriété __ts
(timestamp) du jeu initial contient 1696374425000
comme horloge du mur du client, le compteur comme 0
, et son node-Id comme CLIENT
. Dans la réponse, la propriété __ts
retournée par le magasin d’états contient le wallClock
, le compteur incrémenté par un et le node-Id en tant que StateStore
. Le magasin d’états peut retourner une valeur wallClock
plus élevée si son horloge était à l’avance, en fonction de la façon dont les mises à jour HLC fonctionnent.
Cette version est également retournée sur les demandes GET
, DEL
et VDEL
réussies. Sur ces requêtes, le client ne spécifie pas de __ts
.
Le diagramme suivant illustre la commande GET
:
Remarque
Le timestamp __ts
que le magasin d’états retourne est identique à ce qu’il a retourné lors de la requête SET
initiale.
Si une clé donnée est ultérieurement mise à jour avec un nouveau SET
, le processus est similaire. Le client doit définir sa requête __ts
en fonction de son horloge actuelle. Le magasin d’états met à jour la version de la valeur et retourne __ts
, suivant les règles de mise à jour HLC.
Décalage de l’horloge
Le magasin d’états rejette un __ts
(et également un __ft
) qui est plus d’une minute avant l’horloge locale du magasin d’état.
Le magasin d’états accepte un __ts
qui se trouve derrière l’horloge locale du magasin d’état. Comme spécifié dans l'algorithme HLC, le magasin d'état règle la version de la clé sur son horloge locale parce qu'elle est plus grande.
Jetons de verrouillage et de clôture
Cette section décrit l'objectif et l'utilisation des jetons de verrouillage et de clôture.
Background
Supposons que deux clients MQTT ou plus utilisent la mémoire d'état. Les deux clients veulent écrire sur une clé donnée. Les clients du magasin d'état ont besoin d'un mécanisme pour verrouiller la clé, de sorte qu'un seul client à la fois puisse modifier une clé donnée.
Un exemple de ce scénario se produit dans les systèmes actifs et en attente. Il peut y avoir deux clients qui effectuent la même opération, et l'opération peut inclure le même ensemble de clés de la mémoire d'état. À un moment donné, l'un des clients est actif et l'autre est prêt à prendre immédiatement le relais si le système actif se bloque ou tombe en panne. Dans l'idéal, un seul client devrait écrire dans la mémoire d'état à un moment donné. Cependant, dans les systèmes distribués, il est possible que les deux clients se comportent comme s'ils étaient actifs et qu'ils essaient simultanément d'écrire sur les mêmes clés. Ce scénario crée une condition de course.
Le magasin d'état fournit des mécanismes pour éviter cette condition de course en utilisant des jetons de clôture. Pour plus d’informations sur les jetons d’escrime et la classe de conditions de course qu’ils sont conçus pour se protéger, consultez cet article.
Obtenir un jeton de clôture
Cet exemple suppose que nous avons les éléments suivants :
- Voir
Client1
etClient2
. Ces clients sont des clients de stockage d'état qui agissent comme une paire active et une paire de réserve. LockName
. Le nom d'une clé dans le magasin d'état qui joue le rôle de verrou.ProtectedKey
. La clé qui doit être protégée contre plusieurs rédacteurs.
Les clients tentent d'abord d'obtenir un verrou. Ils obtiennent un verrou en faisant un SET LockName {CLIENT-NAME} NEX PX {TIMEOUT-IN-MILLISECONDS}
. Rappelez-vous des options de définition selon lesquelles l’indicateur NEX
indique que le SET
ne réussit que si l’une des conditions suivantes est remplie :
- La clé était vide
- La valeur de la clé est déjà définie sur la <valeur> et
PX
spécifie le délai d’expiration en millisecondes.
Supposons que Client1
va d’abord avec une requête de SET LockName Client1 NEX PX 10000
. Cette requête lui donne la propriété de LockName
pour 10 000 millisecondes. Si Client2
tente un SET LockName Client2 NEX ...
pendant que Client1
possède le verrou, l’indicateur NEX
indique que la requête Client2
échoue. Client1
doit renouveler ce verrou en envoyant la même commande SET
utilisée pour acquérir le verrou, si Client1
souhaite continuer la propriété.
Remarque
Un SET NX
est conceptuellement équivalent à AcquireLock()
.
Utiliser les jetons de clôture pour les demandes ENSEMBLE
Si Client1
réussit un SET
(« AcquireLock ») sur LockName
, le magasin d’états retourne la version de LockName
en tant qu’horloge logique hybride (HLC) dans la propriété utilisateur __ts
MQTT5.
Lorsqu’un client effectue une demande SET
, il peut éventuellement inclure la propriété utilisateur MQTT5 __ft
pour représenter un « jeton de clôture ». Le __ft
est représenté sous la forme d’un HLC. Le jeton de clôture associé à une paire clé-valeur donnée permet de vérifier la propriété du verrou. Le jeton de clôture peut provenir de n'importe où. Pour ce scénario, il doit provenir de la version de LockName
.
Le diagramme suivant montre le flux du processus de Client1
effectuant une requête SET
sur LockName
:
Ensuite, Client1
utilise la propriété __ts
(Property=1696374425000:1:StateStore
) non modifiée comme base de la propriété __ft
dans la requête de modification ProtectedKey
. Comme toutes les demandes SET
, le client doit définir la propriété __ts
sur ProtectedKey
.
Le diagramme suivant montre le flux du processus de Client1
effectuant une requête SET
sur ProtectedKey
:
Si la requête réussit, à partir de ce stade, ProtectedKey
nécessite un jeton de clôture égal ou supérieur à celui spécifié dans la requête SET
.
Algorithme du jeton de clôture
Le magasin d’états accepte n’importe quel HLC pour le __ts
d’une paire clé-valeur, si la valeur se trouve dans l’asymétrie d’horloge maximale. Il n'en va pas de même pour les jetons de clôture.
L'algorithme de stockage d'état pour les jetons de clôture est le suivant :
- Si une paire clé-valeur n’a pas de jeton d’authentification associé et qu’une requête
SET
définit__ft
, le magasin d’états stocke le__ft
associé à la paire clé-valeur. - Si un jeton de clôture est associé à une paire clé-valeur :
- Si une requête
SET
n’a pas spécifié__ft
, rejetez la demande. - Si une requête
SET
a spécifié un__ft
qui a une valeur HLC plus ancienne que le jeton de clôture associé à la paire clé-valeur, rejetez la requête. - Si une requête
SET
a spécifié un__ft
qui a une valeur HLC égale ou plus récente que le jeton de clôture associé à la paire clé-valeur, acceptez la requête. Le magasin d'état met à jour le jeton de clôture de la paire clé-valeur pour qu'il corresponde à celui défini dans la requête, s'il est plus récent.
- Si une requête
Une fois qu’une clé est marquée avec un jeton de clôture, pour qu’une requête réussisse, les requêtes DEL
et VDEL
nécessitent également que la propriété __ft
soit incluse. L'algorithme est identique au précédent, sauf que le jeton de clôture n'est pas stocké car la clé est supprimée.
Comportement du client
Ces mécanismes de verrouillage reposent sur le bon comportement des clients. Dans l’exemple précédent, un comportement incorrect Client2
n’a pas pu être propriétaire de LockName
et a réussi à effectuer un SET ProtectedKey
en choisissant un jeton de clôture plus récent que le jeton ProtectedKey
. Le magasin d’états n’est pas conscient que LockName
et ProtectedKey
n’ont aucune relation. Par conséquent, le magasin d’états ne vérifie pas que Client2
possède réellement la valeur.
La possibilité pour les clients d'écrire des clés dont ils ne possèdent pas le verrou est un comportement indésirable. Vous pouvez vous prémunir contre ce type de comportement en mettant correctement en œuvre les clients et en utilisant l'authentification pour limiter l'accès aux clés aux seuls clients de confiance.
Notifications
Les clients peuvent s’inscrire auprès du magasin d’états pour recevoir des notifications de clés en cours de modification. Considérez le scénario dans lequel un thermostat utilise la clé de magasin d’état {thermostatName}\setPoint
. D’autres clients du magasin d’états peuvent modifier la valeur de cette clé pour modifier le paramètre setPoint du thermostat. Au lieu d’interroger les modifications, le thermostat peut s’inscrire auprès du magasin d’états pour recevoir des messages lorsque {thermostatName}\setPoint
est modifié.
Messages de requête KEYNOTIFY
Les clients du magasin d’état demandent au magasin d’état de surveiller les modifications d’un keyName
donné en envoyant un message KEYNOTIFY
. Tout comme toutes les demandes de magasin d’états, les clients publient (PUBLISH) un message QoS1 avec ce message via MQTT5 dans la rubrique système statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/command/invoke
du magasin d’états.
La charge utile de la demande est de la forme suivante :
KEYNOTIFY<CR><LF>
{keyName}<CR><LF>
{optionalFields}<CR><LF>
Où :
- KEYNOTIFY est un littéral de chaîne spécifiant la commande.
{keyName}
est le nom de clé sur lequel écouter les notifications. Les caractères génériques ne sont actuellement pas pris en charge.{optionalFields}
Les valeurs de champ facultatives actuellement prises en charge sont les suivantes :{STOP}
S’il existe une notification existante avec le mêmekeyName
etclientId
que cette demande, le magasin d’états la supprime.
L’exemple de sortie suivant montre une demande KEYNOTIFY
pour surveiller la clé SOMEKEY
:
*2<CR><LF>
$9<CR><LF>
KEYNOTIFY<CR><LF>
$7<CR><LF>
SOMEKEY<CR><LF>
Message de réponse KEYNOTIFY
Comme toutes les requêtes RPC du magasin d’états, le magasin d’états retourne sa réponse au Response Topic
et utilise les propriétés Correlation Data
spécifiées à partir de la requête initiale. Pour KEYNOTIFY
, une réponse réussie indique que le magasin d’états a traité la demande. Une fois que le magasin d’états a réussi à traiter la demande, il surveille la clé du client actuel ou arrête la surveillance.
En cas de réussite, la réponse du magasin d’états est la même qu’un SET
réussi.
+OK<CR><LF>
Si un client envoie une demande KEYNOTIFY SOMEKEY STOP
, mais que le magasin d’états ne surveille pas cette clé, la réponse du magasin d’états est identique à la tentative de suppression d’une clé qui n’existe pas.
:0<CR><LF>
Tout autre échec suit le modèle général de rapport d’erreurs du magasin d’états :
-ERR: <DESCRIPTION OF ERROR><CR><LF>
Rubriques et cycle de vie des notifications KEYNOTIFY
Lorsqu’un keyName
surveillé via KEYNOTIFY
est modifié ou supprimé, le magasin d’états envoie une notification au client. La rubrique est déterminée par convention : le client ne spécifie pas la rubrique pendant le processus KEYNOTIFY
.
La rubrique est définie dans l’exemple suivant. Le clientId
est une représentation codée en hexadécimal en majuscules du ClientId MQTT du client qui a lancé la demande KEYNOTIFY
et keyName
est une représentation encodée hexadécimal de la clé qui a changé. Le magasin d’état suit les règles d’encodage Base16 du document RFC 4648 – Encodages de données Base16, Base32 et Base64 pour cet encodage.
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/{clientId}/command/notify/{keyName}
Par exemple, l’Agent MQTT publie un message NOTIFY
envoyé à client-id1
avec le nom de clé modifié SOMEKEY
dans la rubrique :
clients/statestore/v1/FA9AE35F-2F64-47CD-9BFF-08E2B32A0FE8/636C69656E742D696431/command/notify/534F4D454B4559`
Un client qui utilise des notifications doit SUBSCRIBE
à cette rubrique et attendre la réception de SUBACK
avant d’envoyer des demandes KEYNOTIFY
afin qu’aucun message ne soit perdu.
Si un client se déconnecte, il doit se réinscrire à la rubrique de notification KEYNOTIFY
et renvoyer la commande KEYNOTIFY
pour toutes les clés qu’il doit continuer de surveiller. Contrairement aux abonnements MQTT, qui peuvent être conservés sur une session nonclean, le magasin d’états supprime en interne tous les messages KEYNOTIFY
lorsqu’un client donné se déconnecte.
Format du message de notification KEYNOTIFY
Lorsqu’une clé surveillée via KEYNOTIFY
est modifiée, le magasin d’états PUBLISH
un message à la rubrique de notification suivant le format pour indiquer les clients du magasin d’états inscrits pour la modification.
NOTIFY<CR><LF>
{operation}<CR><LF>
{optionalFields}<CR><LF>
Les détails suivants sont inclus dans le message :
NOTIFY
est un littéral de chaîne inclus comme premier argument dans la charge utile, indiquant qu’une notification est arrivée.{operation}
est l’événement qui s’est produit. Actuellement, ces opérations sont les suivantes :SET
la valeur a été modifiée. Cette opération ne peut se produire qu’à la suite d’une commandeSET
à partir d’un client de magasin d’états.DEL
la valeur a été supprimée. Cette opération peut se produire en raison d’une ou commandeDEL
ouVDEL
à partir d’un client de magasin d’états.
optionalFields
- Voir
VALUE
et{MODIFIED-VALUE}
.VALUE
est un littéral de chaîne indiquant que le champ suivant,{MODIFIED-VALUE}
, contient la valeur sur laquelle la clé a été modifiée. Cette valeur est envoyée uniquement en réponse aux clés modifiées en raison d’unSET
.
- Voir
L’exemple de sortie suivant montre un message de notification envoyé lorsque la clé SOMEKEY
est modifiée à la valeur abc
, avec VALUE
inclus, car la demande initiale a spécifié l’option GET
:
*4<CR><LF>
$6<CR><LF>
NOTIFY<CR><LF>
$3<CR><LF>
SET<CR><LF>
$5<CR><LF>
VALUE<CR><LF>
$3<CR><LF>
abc<CR><LF>
Le message de notification KEYNOTIFY
contient l’horodatage de la valeur au moment de la notification d’un client à propos d’une requête SET (valeur mise à jour) ou d’une requête DEL ou VDEL (valeur supprimée). L’horodatage fait partie de la propriété utilisateur __ts MQTT v5 du message. Pour plus d’informations, consultez la section Versions en tant qu’horloges logiques hybrides.