Dans le cadre d'un projet assez subtil, la problématique à régler était de faire communiquer deux noeuds d'un cluster via des messages courts et sans plus de structure que du texte et un peu de méta donnée. Solution simple : un format ad hoc.

Pourquoi un nouveau format ?

Le cas "métier" est le suivant : on envoie d'un noeud à l'autre d'un cluster des demandes courtes, comme par exemple : PING, SET VALUE "A" TO "B". Point important : la machine cible n'est pas nécessairement un super calculateur, on est censé utiliser ce protocole aussi bien sur un 240 coeurs, avec 1 To de mémoire, que sur un rasberry ou une "petite machine". Et donc, il s'agit de faire un peu moins gourmand qu'un serveur web. Aussi, utiliser du HTTP n'était pas non plus la meilleure solution, et on propose plus concis : le SCF.

Comment est structuré un message ?

Un message est constitué aussi bien pour la requête et la réponse des mêmes contenus :

  • un header suivi d'un \n
  • un ensemble de propriétés (optionnel) suivi d'un \n
  • un message sous forme de string (obligatoire)

Voici un exemple

SCP 0.1
CID:fc6f1ee1-24e6-4263-b0a3-a8386c10de5c
MICID:fac4fb5e-aac7-4eb0-8224-24eee5f6ad2b

Encoding:UTF-8

PING

Header

Le header lui même est constitué de :

  1. une ligne qui indique le protocole et sa version : SCP 0.1
  2. un CID (conversational ID) qui est unique toute la durée de vie des échanges de messages. Notre implémentation est un UUID.
  3. Un MICID (message in conversation ID), qui est unique à CID donné. Il permet de distinguer deux messages dont le contenu est par ailleurs identique. Si vous recevez deux fois un "PING", le MICID sert à les distinguer. Notre implémentation est un UUID.

Propriétés

Formellement, ce sont un ensemble de couples clé:valeur séparés par un \n. Les usages sont nombreux, on peut prendre la clé que l'on souhaite, par exemple : CreationDate, TTL, Encoding, etc. La clé s'arrête au premier :, et la ligne au premier \n.

Le message

N'importe quel texte de taille au moins 1. C'est la dernière partie du message.

Implémentations

Pour l'instant, la notre est propriétaire, implémentée en C, en quelques deux cent lignes (sans compter les codes "utilitaires" de type listes, dictionnaires, etc). La simplicité du format le rend facile à implémenter dans à peu près n'importe quel langage.

Usages

  • C'est avant tout un format texte. Donc, il n'est pas initialement prévu pour le binaire, encore que le message puisse être n'importe quoi. Pour du binaire, on recommande de placer dans les propriétés la taille du message, le type pour la déserialisation, voire le MD5 du contenu.
  • C'est aussi un format qui n'a pas de "verbe". Quand vous recevez un GET sur /monapp/clients/inscription, vous avez déjà une idée de la sémantique de la requête. Ce n'est pas le cas du SCP dont la sémantique est portée par le contenu du message. Il est très utile  sur des commandes simples pour lesquelles le contenu suit un DSL implémenté par le client et par le serveur.
  • Il est extensible : on peut tout à fait envoyer plusieurs contenus dans un message. Par exemple, on mettra dans les propriétés autant de lignes que de contenus, et on enverra la concaténation de ceux ci dans le corps du message. Par exemple, vous voulez envoyer un message avec une pièce jointe en texte : Mettez une valeur dans les propriétés qui déclare l'index dans le message où commence la dite pièce jointe.
  • Dans notre cas, on s'en sert pour mettre en place sur un cluster de la communication de base pour une implémentation de Paxos. C'est en tous cas ceci qui a poussé à la mise en oeuvre de cette solution.
 

Comments are closed.

Set your Twitter account name in your settings to use the TwitterBar Section.