Un système de chat en gRPC

Questionnement sur la structure

Le problème exposé dans ce sujet a été résolu.

Salut à tous, il y a quelque temps j’ai commencé à faire un petit système de chat avec gRPC.
L’idée actuel était d’avoir un service qui ne possède qu’une route rpc au travers de laquelle le client et le serveur s’échangent des événements. Cet événement contient un champ qui défini quel type d’événement il est. Il est en suite traité de manière différente par le serveur.

Voici le fichier proto qui à été fait pour cette solution:

syntax = "proto3";

service Chaton {
    // Join to talk with each others
    rpc Join (stream Event) returns (stream Event) {}
}
message Msg {
    string content = 1;
    string author = 2; // Ignored by the server when recieving from clients
}
message Event {
    MsgType type = 1;
    Msg msg = 2;
}
enum MsgType {
    // Open the connection with the server (subscribe to recieve message from him)
    // The message content should be the nick name of the client (can be optional)
    CONNECT = 0;
    // Set the client nickname
    // The message content should be the nick name of the client
    SET_NICKNAME = 1;
    // Send a message, the message content is what is send to other clients
    MESSAGE = 2;
    // Leave the server
    // The message content is what the user say before leaving (can be optional)
    QUIT = 3;
}

Aujourd’hui en revenant sur le projet je me pose la question de faire autrement.
Plutot que d’avoir des enums et de faire un switch dessus coté serveur est ce que je ne devrai pas mieux avoir une route rpc pour chaque evenement ?
On aurait un fichier proto comme suit:

syntax = "proto3";

service Chaton {
    // Join to be part of the chat and receive messages
    rpc Join () returns (stream Msg) {}

    // Say something on the server
    rpc Say (Msg) return ()

    // Rename your self to change your pseudo
    rpc Rename (Msg) return ()
    
    // Quit the server
    rpc Quit (Msg) return ()
}
  
[...]


Que pensez vous des deux solutions proposé ?
Y en a t-il une qui est plus idiomatique que l’autre quand on fait du gRPC ?
Est ce qu’une solution est plus facilement maintenable qu’une autre au long terme ? Notamment si on ajoute des actions plus tard.

+0 -0

Les deux sont assez proches dans l’absolu.

Je dirais que le principal avantage de l’enum de commandes c’est qu’il est plus facile de se prémunir des accès concurrents si jamais les actions ont des effets de bords qui rendent indésirables que deux actions soient exécutées en même temps. Car tu peux les mettre dans une queue à la réception et les exécuter de manière séquentielle de manière générique et simple.

gRPC gère plutôt bien les évolutions du fichier proto pour ajouter de nouvelles actions pour que ce critère ne soit pas fondamentalement un problème de mon expérience. Si du moins tu ne fais pas n’importe quoi.

+2 -0

Perso, je préfère très largement la deuxième option où l’on envoie ses actions via des appels de méthodes : l’interface du service nous renseigne de façon triviale sur ce que peut faire un utilisateur, contrairement à la première solution.

D’une façon générale : modéliser les choses comme des streams bidirectionnels, à moins de ne vraiment pas avoir le choix, n’est pas la meilleure des idées. Si c’est pour que la totalité des communications soit implémentée explicitement comme des messages qu’on s’envoie sur un stream unique, limite autant dégager gRPC et implémenter ton chat avec des sockets, le code aura la même tête, juste en étant capable de faire beaucoup moins de choses avancées (par exemple le chiffrement des communications, le routage via une gateway…).

PS : Après quand on regarde ça en termes de flux d’informations à bas niveau, c’est vrai que techniquement les deux reviennent un peu au même. Mon avis se borne juste à utiliser efficacement gRPC pour ne pas avoir à recoder ce qu’il sait déjà faire pour nous. En l’occurrence : un gros switch sur le type des messages qui arrivent pour les dispatcher au bon endroit.

PPS : En termes de souplesse d’architecture aussi, ça joue : avec la seconde API, tu pourrais très bien imaginer distribuer ton appli à l’extrême et avoir par exemple un binaire qui ne sert qu’une seule de toutes ces méthodes (en imaginant qu’elle soit gourmande) et un second binaire qui sert toutes les autres méthodes, sans rien changer au proto (c’est juste une règle de routage dans la gateway).

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte