Le piquant des technologies de pointe

Chez Nicely, on est fier de notre environnement technique. Chaque composant utilise la technologie la mieux adaptée, un choix qui se base notamment sur les compétences existantes dans les équipes et les performances de la technologie, enjeu crucial pour concilier notre vision de l’IA frugale avec une expérience utilisateur optimale.

Le choix de l’efficacité à un coût, en particulier lors de l’utilisation de technologies émergentes. Nous partageons ici quelques retours d’expérience.

La stratégie

Les technologies sélectionnées doivent apporter flexibilité, scalabilité, sécurité et efficacité. Le langage Go (https://go.dev/) est notre option par défaut. Au regard de nos objectifs, le langage GO représente effectivement le meilleur compromis. Toutefois la variété d’environnements (Linux, Windows, MacOs, Android, IOS) nécessite l’utilisation ponctuelle de langages alternatifs (comme C++ ou Swift). Dans la mesure du possible, nous évitons les langages haut-niveau (PHP ou Python) mais difficilement substituables pour l’IA ou javascript pour le client web (nous ne sommes pas encore prêts pour webassembly, https://webassembly.org/, mais gardons un œil dessus).

Coté bases de données, le No-SQL s’est imposé car nous savions que le modèle serait amené à grandement évoluer au fur et à mesure que la solution mature. MongoDB (https://www.mongodb.com/) par exemple permet cette flexibilité sans le besoin d’un ORM (mapping objet-relationnel).

Que ce soit au niveau software ou bases de données, les clusters doivent être élastiques pour une croissance sans dépendance envers les clouds publiques que l’on s’interdit pour des raisons de sécurité des données.

La sérialisation : de gRPC à QUIC et WebTransport

Pour transmettre un objet en mémoire vers un serveur ou un fichier, il faut une solution pour rendre cet objet ‘linéaire’, de sorte qu’il devienne une série de valeurs à envoyer vers le réseau ou le disque. Pour cela, la solution par défaut aujourd’hui est JSON (https://www.json.org/) qui remplace progressivement XML.

Le concept de gRPC (https://grpc.io/) est en phase avec notre ADN frugal : une solution efficace, portable entre plusieurs langages combinant le protocole de sérialisation protobuf de Google et celui de transport HTTP2, fournissant une efficacité et une certaine élégance au niveau du code. Toutefois, son utilisation sous Windows s’est montrée très laborieuse et l’émergence de HTTP3 à ce moment nous ont forcé à reconsidérer ce choix.

QUIC (https://quicwg.org/), le protocole sous-jacent à HTTP3 avait déjà commencé à prendre du terrain sur TCP et il semblait donc approprié de partir sur la nouvelle génération. De plus, QUIC supporte l’encryption (qui était en surcouche sur TCP pour HTTPS) et les canaux bidirectionnels. Pour la sérialisation, nous avions déjà fait le choix de Colfer (https://github.com/pascaldekloe/colfer) pour son efficacité et le support des langages requis. Encoder les objets en Colfer puis les envoyer dans des canaux bidirectionnels a marché rapidement en Go et C++ mais s’est montré très compliqué en Swift.

Toutefois ce fut l’infrastructure qui nécessita une nouvelle modification. Nous utilisions HAProxy et le support de QUIC coté back-end était trop limité. Pour maintenir la sécurité et cohésion de l’architecture, il a fallu réintroduire une couche HTTP (v3) pour avoir des mécanismes de partage de charge identique avec d’autres flux.

HTTP pur ne nous apporte pas d’avantage au niveau logiciel et pour regagner les capacités de canaux bidirectionnel nous avons essayé d’introduire une autre couche : web transport (https://www.w3.org/TR/webtransport/). Toujours en draft à ce moment, web transport devrait remplacer web sockets dans le futur et capitaliser sur les capacités de QUIC. Mais là encore, les librairies logicielles n'étaient pas mures et l’on a dû faire face à plusieurs problèmes, le plus bloquant étant celui de timeouts.

Au final, nous avons donc abandonné webtransport et créé notre propre protocole directement au-dessus de QUIC avec des mécanismes de load-balancing propriétaires.

Le bilan

Avec le recul, nous nous sommes montrés trop impatients dans la recherche d’optimisation. Le choix n’est pourtant jamais évident car commencer avec une solution temporaire contraint à une future refonte et une migration pour au final un coût plus élevé. En réalité, ce sont ces situations qui permettent d’expérimenter la “vraie agilité”, plus que les meetings scrum.

Mais il y a un autre élément dans le cas de Nicely. Nous ne nous voyons pas comme des suiveurs sur des chemins déjà balisés, mais bien plus comme des explorateurs impatients de découvrir les solutions qui feront tourner les produits du futur.

Nous ne recommandons pas de solution standard car chaque projet est unique et implique une solution adaptée. Nous prenons le parti de souffrir un peu plus sur le code initial plutôt que de subir les migrations. Nous sommes bien conscients que ce n’est que retarder ces migrations et il s’agit donc bien d’estimer la durée de vie de telle ou telle technologie ainsi que les capacités internes à la supporter.