En quoi Protobuf est une fausse-bonne idée.
Je vais rentrer directement dans le vif du sujet en prenant argument par argument et en répondant à chaque fois. Puis j'apporterai les miens à la fin.
1) Les bus applicatifs permettraient de coder en évènementiel.
Oui mais ça ne veut pas dire que c'est la seule technologie permettant de le faire. Vous en connaissez sûrement une autre : les requêtes AJAX sur HTTP. Vous savez ce truc à la base de tous les internets "modernes" sorti en 1996.
Par essence une requête AJAX est asynchrone et c'est lorsque le serveur notifie le client qu'il a traité sa demande (ce qui est la définition même d'un évènement) qu'une fonction de call-back est invoquée.
2) Passer par un bus applicatif réduirait le couplage entre les services.
En général on me sort cet argument face à RESTful ce à quoi je réponds : le degré de couplage est le même.
Effectivement en RESTful ce qui compte c'est le chemin utilisé et un fichier JSON qui contient les données. Il ne s'agit pas là d'invoquer une méthode via RMI, ni d'employer la même technologie côté client et côté serveur, il s'agit d'envoyer un fichier texte contenant les bonnes informations sur une URL. Wouah mais quel couplage ! #Unbelievable
Nous sommes déjà au degré utile et essentiel de découplage. Commencer à vouloir s'abstraire de l'URL est un non-sens d'autant qu'elle se retrouvera quand même dans les messages des bus comme Kafka mais sous une autre forme : le type du message.
Je m'explique : pour qu'un message soit dépilé par le bon service, il faut qu'il soit typé (ie. je contiens tel contenu et j'incarne telle demande), or le typage d'une demande en RESTful c'est ni plus ni moins que l'URL. Avec les bus applicatifs comme Kafka, nous représentons ce typage sous la forme d'une entrée de type clef-valeur dans un header mais cela revient à la même chose que de contacter une URL. C'est juste moins facile à relire car les protocoles sont binaires et non textuels (cf. KafkaMessage) donc ça paraît "plus découplé" mais ça ne l'est ni plus ni moins.
3) Les bus applicatifs permettraient de gérer des queues de messages.
En réalité cet argument n'en est pas un. Nous avons ajouté de la puissance de calcul dans le bus dont le rôle sera d'encaisser les pics de charge ; or pourquoi ne pas affecter cette puissance de calcul (en générale inhumaine lorsque nous parlons d'un cluster Kafka) directement dans les µ-services ? (ndr. qui sont eux aussi un anti-pattern d'architecture)
Dit autrement, nous préférons affecter de la puissance de calcul à des unités de stockage de messages, rajoutant ainsi des latences et augmentant les coûts d'infrastructure plutôt qu'aux unités de traitement qui fournissent elles des calculs utiles.
Je suis favorable aux queues lorsqu'elles sont à l'intérieur d'une application, car elles aident à mettre en place des algorithmes de calculs mutli-threads et parallèles pour ainsi tirer parti de 100% des hardwares mutli-cpus / multi-cores.
Au niveau inter-applicatif c'est une très mauvaise idée car cela fait reposer nos SI sur l'élément le moins fiable du monde : le réseau.
4) Les bus applicatifs seraient plus sécurisés en forçant une rupture protocolaire.
L'argument du changement de protocole dépend de comment fonctionne le bus et de son implémentation. Par exemple les bus qui travaillent en SOAP sur HTTP fonctionnent sur HTTP... Comme nos requêtes REST en somme... #ChangementDeProtocoleSur20
Ensuite, la sécurité ce n'est pas qu'une simple histoire de protocole, c'est toute l'architecture qui doit être pensée pour être résistante aux attaques. Cet argument laisse accroire que la sécurité est une chose facile et que nous aurions magiquement augmenté le niveau juste par la présence d'un sacro-saint bus, ce qui est faux.
Enfin, en quoi un changement de protocole sécurise quoi que ce soit ? Si j'envoie un message via un bus, quoi qu'il arrive ce dernier sera traduit dans un format interprétable par l'application, si je peux effectuer une injection parce que l'application tolère les injections, je pourrai quand même attaquer le système.
Souvent, on me rétorque à cet argument que le bus peut faire des contrôles anti-injections par exemple, mais ce sont les mêmes personnes qui me disent de l'autre côté qu'un bon bus reste au niveau du réseau et qu'il doit être neutre au niveau application : décide-toi camarade.
Pour moi ce qui transporte un message ou une requête ne doit transporter que le message ou la requête et ne rien faire d'autre. Quand j'envoie ou que je reçois une lettre par la poste je ne veux pas que la poste ouvre ma lettre et en modifie le contenu "pour me protéger". #Censure Pour mes applications c'est pareil, je décide seule de ce qui est une attaque et de ce qui est une demande, pas le bus, donc pas de sécurité à son niveau. #SegragationOfConcerns
5) Le monitoring réseau est plus facile avec un bus.
Le bus est un endroit centralisé par lequel tout transite, donc enregistrer qui s'adresse à qui semble plus simple que faire la même chose dans un réseau maillé à la sauce internet où n'importe qui peut contacter n'importe qui d'autre.
Alors cela est vrai lorsque les bus ne sont faits que d'une seule instance... Or si une seule et unique machine peut encaisser toute la charge de vos messages, déjà je vous pose la question de l'intérêt d'avoir mis en place un bus pour un SI aussi peu complexe avec une volumétrie aussi faible mais admettons...
En général les bus applicatifs sont de très gros clusters avec des systèmes de réplication inter-instances... Les gens qui me parlent de monitoring vont me dire que "grâce au bus je sais qui envoie des messages au cluster de mon bus et qui reçoit des messages du cluster de mon bus". Ok... Mais que se passe-t-il à l'intérieur du cluster ? Quel trajet le message a-t-il effectué dans cette #BoiteNoire ?
En y regardant de plus prêt nous nous rendons compte qu'il existe une case à l'intérieur de laquelle nous n'analysons plus rien et nous décrétons que cette case n'est pas à superviser puisque c'est le bus lui-même ; ce qui revient à superviser un routeur.
Or ne regarder que ce qui est extérieur au bus se rapporte à monitorer la périphérie du SI, c'est-à-dire nos services et c'est déjà chose possible avec des logs produits par les services eux-mêmes + ELK pour un coût et une complexité d'infrastructure dix fois moindre.
Je sais que Kafka est plus intelligente et permet de se monitorer elle-même, mais cela ne répond pas à la question du nombre d'instances supplémentaires à gérer du fait de sa seule présence, ni même de l'expertise que cela requiert ou encore de la manière dont Kafka va contraindre la façon de coder les services.
6) Les bus me permettraient de changer un service sans impacter les autres.
L'idée sous-jacente est de dire que comme tout le monde parle au bus alors les services ne se connaissent pas entre-eux. Il devient donc possible de changer un service sans devoir patcher les autres.
En réalité ce coût de transformation est déporté non pas pendant la mise à jour du service mais au moment de la migration du bus A vers un autre bus B.
Sauf que l'économie de ces petits coûts traités au fil de l'eau se métamorphosera en supra-giga-facture lors de la big-bang transformation qui consistera à sortir totalement le SI du bus A. C'est évident, puisque tout le monde parlant au bus, aussitôt que l'on changera de bus, il faudra mettre à jour tout le monde avec la complexité et le risque que ce genre de "migration" impose. Vous le sentez l'anti-pattern du point de vue du CTO ou d'une DSI ?
Je préfère disposer d'une communication ad-hoc entre plusieurs services REST s'appuyant sur des Swagger faisant office de contrat d'interfaçage. Ainsi tant que tout le monde parle le bon JSON, ça marche point.
Pas de protocole particulier, pas de lib "kafka-client" à tirer dans mon application, pas de dépendances vers des tiers, juste des fichiers textes ayant une structure (CSV, JSON, XML, YAML, etc) et que j'envoie ou reçois sur le réseau ; avec des mises à jours petites, fréquentes et réalisées en continue pour faire virer notre paquebot de SI sereinement.
Je peux en plus choisir un format adapté qu'il soit plat (properties) ou arborescent (JSON) là ou Kafka m'impose du plat en clef-valeur. Cette contrainte rend juste votre vie difficile pour représenter une hiérarchie d'objets, heureusement ça n'arrive que tout le temps...
Il faut bien comprendre que lorsqu'un Swagger change pour ajouter un nouvel attribut par exemple, il faut alors changer tous les clients. Mais c'est également le cas avec des bus comme Kafka ! En effet, si un message nécessite une valeur supplémentaire, il faut que tous les clients émettant ce message intègrent cette nouvelle valeur. Mais alors où se trouve le découplage des bus par rapport à REST ? Où se trouvent el famoso "mise à jour sans impact" ? Réponse : nulle part, c'est un mythe.
Nous voici arrivés à la partie contre-arguments (qui va être courte car j'en ai marre d'écrire) :
Les bus sont des SPOF (Single Point Of Failure) mais pourquoi ?
Au niveau du réseau
Comme tout passe par le bus, alors si le bus tombe tout tombe. C'est la raison pour laquelle Kafka a émergé ; puisque si un nœud Kafka tombe, alors il en existe d'autres pour assurer le travail et l'engouement pour Kafka est à mon sens le témoin du fait que les bus mono-instances étaient encore plus des anti-patterns. Mais quid des difficultés d'administration de Kafka ?
Je rappelle qu'un service doit déclarer les adresses de tous les nœuds Kafka pour se connecter au cluster (au cas où le seul nœud déclaré aurait lâché). Je dois donc paramétrer mon application pour qu'elle ait une connaissance de l'infrastructure alors que celle-ci devrait être agnostique de cette infrastructure. Nous revenons en arrière de 20 ans (promis je ferai un poste expliquant en quoi Docker fait la même chose vis-à-vis du build lié à la sécurité).
Le nombre d'instances à administrer augmentent mais pas seulement... Le type d'instances aussi !
Et oui il faut administrer les instances du bus en plus des instances applicatives mais en plus il faut disposer d'admin-sys ayant des compétences sur les applications ET sur le bus !
Alors du point de vue du cabinet de conseil c'est merveilleux puisque je peux fourrer encore plus de prestas ! #Money Mais du point de vue du CTO ou de la DSI, c'est mon porte-feuille qui se fait mettre à mal.
Et là je ne parle pas que de compétences, arguons que chaque instance tourne sur du hardware en dernier recours et que ce hardware a un coût. Plus d'instances => Plus de hardware ou du hardware plus gros et donc plus cher ! C'est le second effet kiss-cool au porte-monnaie.
Mais il y en a un troisième !! Il faut que je recrute des développeurs qui maîtrisent le bus. Vous savez les développeurs Kafka par exemple... Sauf que compétences en plus => tarifs plus élevés. Et cela engendre des difficultés de recrutement d'une part et une sensibilité accrue au turner-over d'autre part surtout quand l'expert Kafka nous quitte...
Les schémas du SI intégrant un bus masquent l'horreur de la réalité.
Avant les bus applicatifs, les architectes fournissaient des schémas avec plein de boites et encore plus de flèches le tout partant dans tous les sens. C'était alors triviale de constater l'ampleur du grand merdier et donc de réclamer une simplification du SI aux architectes dont le travail était manifestement défaillant.
Avec un bus, nous nous retrouvons avec les boites applicatives en périphérie de ces schémas et une plus grosse au centre : celle du bus lui-même. Là le schéma est propre, harmonisé, au moyen une belle structure en étoile où chaque composant ne s'adresse qu'au bus... #PowerPointSur20
Soyons clairs, c'est le même bordel à l'intérieur de la grosse boi-boite qui représente le bus que ça ne l'était avant sans la présence du bus. Sauf que ce souk devient invisible quand on ne se rend pas sur le terrain, en observant les flux et le code... Mais ce que le CTO ne voit pas ne lui pose pas de problème n'est-ce pas ?
Illustration du problème AVANT
Illustration du problème APRES
Comment identifier l'endroit où la complexité est la plus dense ? Comment y affecter des personnes et mesurer sans effort l'ampleur des difficultés qu'elles vont affronter si tous ces schémas avec ces flèches dans tous les sens ont été effacés du regard ? Comment justifier les coûts budgétaires aussi élevés à chaque mise à jour alors que notre SI paraît si simple, si joli, si sophistiqué avec sa structure en étoile dans de beaux Power-Point animés ?
Si certains architectes aiment autant les bus, je pense que c'est parce qu'ils peuvent montrer à quel point ils brillent, leurs schémas devenant clairs, limpides, dignes des experts qu'ils sont au vu de leurs tarifs. Et toute la difficulté retombera alors sur le dos des développeurs, vous savez ces "tocards" payés à pas cher et importés de l'étranger... De parfaits coupables pour des experts influents et bien-pensants face à la certitude que les devs soient des incompétents.
Je résumerais ma position sur un principe : KISS (Keep It Simple, Stupid !). Cela vaut pour du code, cela vaut aussi pour le SI.
Bon, je vais rebondir sur ce repost de HowTommy (et d'une manière générale à ses écrits ainsi qu'à ceux de Neko) parce que les deux sont victimes du même problème...
Je cite :
Je lis bcp de bêtises sur le monteur de Squeezie, alors on va faire simple : être d’extrême droite ce n’est pas "juste une opinion politique", c’est adhérer à un projet global, fondamentalement raciste, à tendance génocidaire, qui place une hiérarchie entre les êtres humains.
Donc non, dans l’absolu, on va pas lâcher la grappe à quelqu’un parce qu’il « exprime juste ses opinions politiques », vu que ce que tu appelles opinion a une conséquence réelle et morbide sur le monde réel dans lequel nous vivons mais t’es clairement pas concerné.e.
On est en 2020 wesh on devrait même pas en discuter encore, ça devrait être la base de la base.
L'arnaque de l'échiquier politique
D'une commune mesure, les media représentent l'échiquier politique sur une dimension comme ceci :
Le bien Ceukonpakompri Le Mâââl
|---------------------------------|---------------------------------|
Là se trouve les Là se trouve
"intellectuels tous les connards
de gauche" et racistes de droite
Mais n'y a-t-il que moi que ça choque ? Typiquement, on peut être pour les frontières et contre l'immigration afin de protéger le prolétariat du casse du droit du travail issu d'une main d’œuvre abondante, désespérée et pas chère (tenaillant ainsi les bas salaires) et ainsi lutter contre l'accumulation sans limite des richesses par l'actionnariat qui n'a aucun autre talent que celui d'avoir hériter son argent.
D'ailleurs, c'est un petit peu la thèse de ce raciste célèbre qui s'appelle Karl Marx dans son ouvrage "Le Capital".
Cette représentation gauche-droite absurde qui aplanit 99,999...% de la réalité n'existe que pour une seule raison : elle est particulièrement clivante. Soit tu es de mon côté, soit tu es de leur côté... Vous la sentez venir la représentation de merde ?
L'échiquier politique est en réalité multi-dimensionnel
Séparer des idées qui n'ont rien à voir en "une partie à gauche" et "l'autre partie à droite" - comme si elles pouvaient s’agréger naturellement parce qu'il existerait un camp du bien constitué de gens "qui ont compris" - est une vision enfantine et très Hollywoodienne du monde où il existe en "zentils" et les "mézants"...
Par exemple une personne lambda peut, sans qu'il n'y ait la moindre contradiction :
- Lutter contre le racisme car elle considère que l'idée que la couleur de peau conditionne tout chez un individu est infondée, stupide et nocive.
- Être croyante car elle a été élevée comme ça.
- Être contre les sectes car elles manipulent les gens pour leur profit (ndr. la religion ce n'est pas l'église).
- Être pour une sortie de l'UE car elle veut protéger les ouvriers de son pays du dumping social.
- Être contre la GPA (Grossesse Pour Autrui) car elle ne veut pas monnayer le corps des femmes pauvres et ses croyances vont contre.
- Être pour plus de sécurité dans son pays car elle a peur de la violence et de la délinquance.
- Être pour un contrôle strict et répressif des forces de police pour éviter une montée du totalitarisme.
- Être pour le nucléaire à court et moyen termes car c'est ce qui pollue le moins à cette heure.
- Être en faveur des énergies renouvelables d'une manière générale car c'est le moins risqué en cas de cataclysme.
- Être pour la cotisation sociale car cela finance des services publics
- Être contre les impôts car ils finances les banques.
- ...
Vous m'avez comprise, tous ces éléments ne sont pas contradictoires entre-eux, ils sont complémentaires et ne peuvent se représenter que dans un espace multidimensionnel car ils sont orthogonaux entre-eux. Mais du coup où se trouve ce personnage ? Dans quel camp le mettriez-vous avec la représentation classique ?
La réponse est nulpart, car le clivage gauche-droite ne permet pas de positionner un tel individu et c'est bien le but de cette dichotomie politique fictive. Une fois que l'on cesse de penser les individus comme des êtres complexes mais uniquement comme des éléments adhérents totalement à des agrégats forcés d'idées (aka les fachos, les gauchiasses, etc) alors il n'est plus possible de les penser comme des alliés potentiels dès qu'ils se trouvent dans un agrégat opposé.
Le pire, c'est qu'un tout petit critère arbitraire permet d'exclure n'importe qui, favorisant le "diviser pour mieux régner" au bénéfice des puissants qui jubilent de cette stupidité de masse. Et c'est ce qui est arrivé au monteur de Squeezie, pour un marque page, tiré d'un screenshot, pris à partir d'un zoom, fait depuis une vidéo de Squeezie et pointant vers une page du site E&R, ce monteur est devenu le mal incarné et Squeezie cautionne les fachos... #SophismeParAssimilation
En résumé
Je vais ressortir l'argument coup de poing des followers du compte Twitter parce qu'il s'applique bien ici aussi je trouve :
Cessez de penser dans le cadre que l'on vous impose et émancipez-vous, sans cela vous resterez des prolétaires toute votre vie car seuls pour vous défendre et combattre des gens plus puissants que vous et qui quant à eux mettent leurs différences de côté pour travailler en équipe à leur bénéfice commun.