Etat de l’internet en l’an 10 des réseaux sociaux (1) : les prémisses

De nombreuses réflexions que je me fais depuis plusieurs années sur internet, les contenus qui y sont publiés et les dispositifs permettant d’y accéder se sont cristallisées d’un seul coup dans mon esprit en une idée de série d’articles à la lecture de cette tribune d’Hossein Derakhshan, blogueur irano-canadien qui à sa sortie de prison en Iran a découvert un paysage de la diffusion de contenus sur internet nouvellement dominé par les réseaux sociaux. Je ne partage pas totalement le pessimisme de ce texte, mais il pose des questions extrêmement intéressantes sur l’évolution actuelle d’internet, auxquelles je vais tenter d’apporter des réponses solidement ancrées dans la technique mais à la portée universelle.

Pour ce premier article, je vais me pencher sur les racines techniques d’internet qui ont défini son identité et assuré son succès.

Internet, le réseau des réseaux

Les premiers réseaux informatiques liant des ordinateurs entre eux datent de la fin des années 50, et reliaient des machines physiquement proches et en tout état de cause, la communication se passait de façon homogène, c’est-à-dire que d’une manière logique, l’information transmise ne traversait qu’une seule barrière, la limite qui sépare un ordinateur du medium physique la transportant jusqu’à l’autre ordinateur.

Réseau simple

Les années 60 virent le développement des réseaux locaux, et ce qui est considéré comme le premier réseau interconnecté, ARPANET, est né en 1969. Il fonctionnait de la façon suivante : des machines locales étaient toutes reliées à un ancêtre de routeur appelé IMP via une liaison série maison, et ces IMP discutaient entre eux en utilisant des liaisons téléphoniques dédiées – il est amusant de noter que la première RFC (Requests For Comments, forme de documents de spécifications des éléments techniques d’internet) décrit le fonctionnement des IMP. Les deux points révolutionnaires de cette approche sont la notion de commutation de paquets, et la capacité à traverser plusieurs barrières logiques avec des media physiques potentiellement différents pour transporter les données offerte par le routeur.

Jusqu’à l’invention de la commutation de paquets, une ligne de communication était dédiée à une conversation unique, comme avec le téléphone ; chaque paquet transporte l’information de la source et de la cible, de façon à ce que tous ceux qui empruntent la ligne de communication sachent si l’information leur est destinée.

Le routeur, quant à lui, est là pour gérer le trafic allant et venant vers les réseaux distants ; c’est un traducteur, connaissant à la fois la langue et les personnalités locales, ainsi que l’espéranto commun et les communautés distantes.

Le schéma précédent devient :

Réseau routé

 

Une fois ce modèle mis en oeuvre, petit à petit, étape par étape, en améliorant les protocoles de communication, en étendant le nombre de routeurs traversables pour lier deux machines, s’est créé au début des années 90 un réseau mondial, auquel la plupart des réseaux locaux sont connectés.

Internet est donc à sa source même une technologie reliant des ordinateurs entre eux, sur la base de langages techniques appelés protocoles, sans donner d’importance particulière aux nœuds, si ce n’est aux routeurs qui ont comme rôle spécifique d’assurer des ponts entre des réseaux hétérogènes.

L’hypertexte, réseau des contenus

Tout cela est bel et bon, mais comme les ordinateurs ne sont que des machines sans intelligence, il faut bien que la communication entre les machines serve à convoyer des informations intéressant les êtres humains. Un service auquel on pense immédiatement est le partage de fichiers distants où un serveur met à disposition une liste de fichiers accessibles ; le protocole FTP remplit ce besoin dès 1971 avec la RFC 114. On peut résumer l’architecture de partage de contenus ainsi créée par le schéma suivant :

ContenuCentralise

 

Ce qui frappe immédiatement dans cette organisation, c’est qu’elle ne correspond pas à l’organisation technique des machines ; autant le transfert de données bas niveau entre ordinateurs est par essence décentralisé et symétrique, autant dans ce mode, la consommation de contenus est centralisée et asymétrique. D’un point de vue fonctionnel, elle limite le partage d’informations ; d’un point de vue technique, elle pose de gros  problèmes de performance car certains nœuds du réseau, ceux qui servent le contenu, doivent être traités différemment des autres car ils seront plus sollicités. On peut noter cependant qu’elle correspond assez bien à l’idée juridique que les pays développés se font de la propriété intellectuelle.

En réponse à cette inadéquation fonctionnelle de la fourniture de contenus avec les possibilités techniques du réseau, a été créé au CERN par Tim Berners-Lee et Robert Cailliau le World Wide Web, un réseau des contenus, avec comme notion fondamentale le lien hypertexte qui permet à un document de faire référence à un autre document, parfois sur le même serveur de contenus, parfois sur un serveur à l’autre bout du monde. Comme vous avez pu le constater avec mes magnifiques schémas ci-dessus, faire un graphique parlant de ce réseau de contenus est au-delà de mes capacités ; je me contenterai donc de reprendre un exemple de représentation visible dans wikipedia :

This Wikipedia and Wikimedia Commons image is from the user Chris 73 and is freely available at http://commons.wikimedia.org/wiki/File:WorldWideWebAroundWikipedia.png under the creative commons cc-by-sa 3.0 license.

La question technique posée par la centralisation des serveurs de contenus n’est pas résolue par cette solution ; c’est le rôle des CDN (Content Delivery Network) qui dupliquent les contenus sur des machines au plus proche des consommateurs, et du peer to peer, qui distribuent la responsabilité de fournir le contenu à un maximum de nœuds dans le réseau, mais c’est une autre histoire.

Conclusion

S’appuyant sur ces deux technologies, Internet est prêt à envahir le monde : un réseau extensible d’ordinateurs et un réseau extensible de contenus, marchant la main dans la main, construits principalement par la communauté scientifique, dans un soucis de partage du savoir et de la puissance de calcul. Dans le second article, nous verrons ce que la première phase de l’ouverture au grand public en aura fait.

Analyser les erreurs

Comme tout ce qui n’est pas testé ne fonctionne pas, tout développeur a forcément des erreurs à corriger dans son code ; je laisse la démonstration de cette assertion au lecteur. D’après mon expérience, la capacité à bien utiliser les outils à sa disposition pour analyser les erreurs dans son programme est un des facteurs ayant le plus d’impact sur la rapidité des développeurs à livrer une application opérationnelle, d’autant plus pour les applications webs qui sont constituées de nombreuses couches de code interagissant les unes avec les autres. Sans prétendre à l’exhaustivité, cet article va vous donner les quelques pistes à explorer pour accélérer le processus d’analyse.

RTFL! (Read the Fucking Logs!)

De très nombreuses bibliothèques, frameworks et autres environnements d’exécution comme les navigateurs internet ou les machines virtuelles – et même les systèmes d’exploitation eux-mêmes – ont la politesse de créer des journaux dans lesquels on peut trouver des informations sur l’exécution des programmes. Rien n’est plus exaspérant pour un référent technique comme moi que de voir arriver un développeur coincé, de lui demander « que vois-tu dans les logs ? » et de s’entendre répondre « je ne sais pas, je n’ai pas regardé… ». Voici une liste de journaux utiles.

Notre framework utilise log4net de l’Apache Software Foundation pour journaliser ses opérations ; par exemple, en mode ERROR, toutes les requêtes SQL provoquant une exception sont écrites dans le journal, et en mode DEBUG, toutes les requêtes y sont écrites. Si vous souhaitez ajouter une journalisation à vos programmes, je vous conseille log4net et ses équivalents sur d’autres plateformes, l’ancêtre log4j, log4php, etc. qui sont peu invasifs, performants, flexibles et possèdent de nombreuses méthodes d’écriture (fichier, journal d’évènement sous Windows, email, console, bases de données, trace ASP.NET, socket, etc.).

PHP peut afficher les erreurs dans la sortie HTML, ce qui est une très mauvaise idée pour des raisons de sécurité ; du coup, les administrateurs désactivent généralement complètement la journalisation des erreurs, alors qu’elles peuvent être très facilement envoyées vers un fichier précis ou vers les journaux système. Quand je débarque dans un code PHP inconnu, je commence généralement par activer la sortie des erreurs, et là c’est festival avant même d’avoir commencé à corriger les problèmes qu’on m’avait soumis !

Sous Windows, le journal d’événements est une mine d’or d’informations pour le débogage. Les services du système d’exploitation y écrivent toutes leurs erreurs, par exemple IIS ou le service de relais SMTP qui y met les messages d’erreur des serveurs SMTP distants. La machine virtuelle .NET y journalise les exceptions non interceptées avec la pile d’appels au moment de l’erreur. L’onglet « Sécurité » contient les erreurs d’authentification et, encore plus intéressant, les traces des audits d’accès aux ressources. Ce dernier outil, assez méconnu, est un don du ciel quand vous ne comprenez pas un problème d’accès à un fichier ; en effet, plus les problématiques de sécurité se font prégnantes, plus les systèmes d’exploitation ont tendance à faire exécuter les programmes par des profils à faibles autorisations, voire à ne pas charger totalement les profils – une spécialité de Windows. Si vous souhaitez comprendre pourquoi vous n’avez pas accès à tel ou tel fichier, vous devez effectuer les opérations suivantes :

  • cibler la ressource
  • activer l’audit sur la ressource (pour un fichier ou un répertoire, aller dans ses propriétés, onglet Sécurité, cliquer sur Avancé puis aller dans l’onglet Audit et activer les audits utiles)
  • activer l’audit sur la machine ; pour cela, aller dans Stratégie de sécurité locale dans les Outils d’administration, déplier Stratégies locales puis Stratégies d’audit, et activer les échecs et/ou les réussites sur la catégorie qui vous intéresse
  • réitérer la tentative d’accès
  • lire le journal Sécurité, dans lequel vous saurez quel utilisateur a tenté avec ou sans succès à la ressource, depuis quel programme, etc.
  • une fois les problèmes réglés, désactiver les audits pour éviter de graver le journal pour le plaisir

Les systèmes de gestion de bases de données relationnels peuvent, en fonction de leur configuration, écrire des traces des requêtes erronées – configuration par défaut de PostgreSQL – ou des requêtes coûteuses – configuration par défaut de MySQL. Ils supportent tous l’instruction EXPLAIN donnant le plan d’exécution, ont des outils de trace avancés, tiers ou natifs, capables de proposer des index pour accélérer les requêtes.

Les navigateurs internet modernes ont des outils pour les développeurs qui auraient fait baver le petit François à ses débuts de développeur web en 1997 : console avec toutes les erreurs, suivi de variables javascript, débogueur avec points d’arrêt et instruction d’entrée dans le débogueur (debugger), liste de règles CSS appliquées à un élément et possibilité de tester des modifications sur icelles, liste des ressources chargées avec source du chargement, temps d’attente du premier octet, temps de téléchargement, en-têtes HTTP en entrée et en sortie, remis en forme indentée des fichiers javascript compressés, manipulation du code HTML, simulation de résolutions tierces et d’interfaces utilisateur tactiles…

Les débogueurs modernes peuvent prendre la main sur un programme déjà lancé, sur la machine locale ou même sur une machine distante, en s’attachant à ce programme, en dehors de leur capacité bien connue de lancer un programme directement en mode débogage.

Et même quand vous n’avez pas accès à la machine, localement ou à distance, vous pouvez demander à l’utilisateur de faire un export mémoire exploitable par votre débogueur, par exemple avec procdump et Visual Studio pour Windows, natif ou .NET.

En bref, avant quoi que ce soit d’autre, RTFL!

Le mille-feuilles de l’informatique distribuée

Très longtemps, les programmes informatiques se sont exécutés sur une machine unique, sans collaboration avec d’autres ; au pire, on avait affaire à un serveur tout-puissant et un terminal d’affichage stupide.

Aujourd’hui, avec les développement des réseaux, le gros des applications d’entreprise et même grands public distribuent les tâches à plusieurs ordinateurs collaborant pour rendre le service attendu. C’est en particulier le cas du développement web, où vous avez au minimum un serveur manipulant des données de référence pour les rendre intelligibles et modifiables par un client exécutant l’interface utilisateur dans un navigateur web. Le cas général  comprend côté serveur des systèmes de stockage de données ayant leur propre langage, SQL ou non, un serveur web pour gérer les connexions réseau, une plateforme logicielle intégrée au serveur web pour tout lier, et côté client du code HTML et CSS définissant l’apparence des écrans et du code javascript pour gérer l’interaction avec l’utilisateur.

En cas de bogue, la couche dans laquelle il survient est rarement difficile à trouver, même si certaines erreurs réseau peuvent être un peu plus vicieuses – comme les validations de certificats SSL. Par contre, il peut s’avérer nettement plus compliqué de déterminer dans quelle couche la correction doit être effectuée : si la reptation jusqu’au client d’une donnée stockée dans une base relationnelle provoque une erreur dans le code javascript, par exemple une « ‘ » non échappée dans une chaîne de caractères, l’erreur se manifeste dans le code javascript exécuté sur le poste du client, alors que la correction à apporter doit l’être dans le code serveur le générant – et pas dans la base, dont les données doivent être agnostiques de la façon dont elles seront utilisées.

Il n’existe pas de règle s’appliquant à toutes les architectures distribuées pour débusquer ce genre d’erreurs, mais en être conscient est déjà un début de solution.

Utiliser les moteurs de recherche

Quand j’ai commencé à programmer, internet n’existait pas pour le grand public ; nous n’avions comme seules ressources que la documentation du langage – 700 pages sur papier bible pour Turbo Pascal 5.5 – et les articles de magazines et livres que nous pouvions trouver en français, autant dire pas grand chose.

Aujourd’hui, il est rare de tomber sur un problème dont personne n’a publié la solution sur internet, mais encore faut-il savoir comment chercher.

Première règle : chercher en anglais. On peut hurler à l’hégémonie anglo-saxonne autant que l’on voudra – j’écris en français volontairement pour créer du contenu francophone sur l’informatique – malgré ses 275 millions de locuteurs, notre langue est loin d’être la plus présente sur internet. Si votre message d’erreur est en français – ou dans n’importe quelle autre langue – traduisez-le du mieux que vous pouvez ; les systèmes de suggestion automatiques peuvent vous aider, et certains services existent pour certaines plateformes. Petit à petit, à force de parcourir les documentations et forums en anglais, vous acquerrez le vocabulaire ad hoc. En désespoir de cause, pour des plateformes traduisant les messages d’erreur en utilisant les paramètres régionaux comme .NET ou Java, vous pouvez forcer la langue d’exécution du programme pour obtenir le message d’erreur en anglais.

Deuxième règle : même si vous cherchez sur un site précis, n’utilisez pas la recherche intégrée du site, utilisez votre moteur de recherche préféré et sa fonctionnalité de limitation à un nom de domaine. Google ou Bing indexent mieux les sites que les sites eux-mêmes, et ils supportent la notation site:nomdedomaine.tld. De toutes façons, les meilleures ressources en dehors des documentations officielles, comme stackoverflow.com ou codeproject.com, sont par nécessité très bien construits pour les moteurs de recherche.

Troisième règle : si le message d’erreur ne donne pas de résultat, passer aux noms des fonctions employées assortis de mots clés correspondant à l’erreur et du langage de programmation ou la plateforme – .NET et Java par exemple ont tendance à avoir des noms d’objets assez semblables – et ça vous évite aussi les pages visant le grand public plutôt que les développeurs – les utilisateurs aussi voient des messages d’erreur. Les noms de méthode dans la pile d’appel peuvent aider à cibler plus précisément la recherche.

Enfin, si jamais vous résolvez un problème sans en passer par internet, ou après une longue recherche et un croisement de plusieurs ressources, rendez la solution disponible pour les copains !

Mono, Postgresql et UTF-8

Nous avons déployé récemment notre première application métier sur une plateforme Linux / Apache / Mono / Postgresql sur un serveur tiers, et nous avons eu un problème pas très facile à diagnostiquer et dont je vais partager la solution au cas où cela serve à quelqu’un.

La base de données postgresql était bien configurée en UTF-8, le paramètre serveur « client_encoding » était bien configuré en UTF-8, mais le site persistait à nous afficher les accents de la base avec des « ? », et de même, à l’enregistrement, les accents se transformaient en « ? ». Nous avons regardé la documentation de Npgsql, le driver .NET Postgresql, où nous avons trouvé un paramètre « Encoding » mais déclaré obsolète et comme valant toujours unicode. Nous avons fait exécuter « SHOW client_encoding » qui doit renvoyer la valeur du paramètre pour la session, et avons reçu « UTF-8 ».

Finalement, nous avons trouvé une documentation Npgsql chez Mono qui conseillait d’utiliser le paramètre Encoding avec la valeur UNICODE si on avait des problèmes avec UTF-8 (attention, UNICODE en respectant les majuscules !). Et effectivement, en rajoutant Encoding=UNICODE dans la chaîne de connexion, les « ? » sont redevenus des caractères accentués.

Résumons : la base est en UTF-8, la valeur par défaut pour le codage de caractères de la connexion est UTF-8, la connexion est bien en UTF-8, mais le driver Npgsql embarqué par Mono s’embête à saloper toutes les chaînes avec une option déclarée comme obsolète par les développeurs de Npgsql eux-mêmes… Merci pour ce moment !