Article original : The boring technology behind a one-person Internet company
Par Wenbin Fang
Listen Notes est un moteur de recherche et une base de données de podcasts. La technologie derrière Listen Notes est en réalité très très ennuyeuse. Pas d'IA, pas de deep learning, pas de blockchain. Tout homme qui doit dire que j'utilise l'IA n'utilise pas la vraie IA :)
Après avoir lu cet article, vous devriez être en mesure de reproduire ce que j'ai construit pour Listen Notes ou de faire facilement quelque chose de similaire. Vous n'avez pas besoin d'embaucher beaucoup d'ingénieurs. Souvenez-vous, quand Instagram a levé 57,5 millions de dollars et a été racheté par Facebook pour 1 milliard de dollars, ils n'avaient que 13 employés et pas tous étaient ingénieurs. L'histoire d'Instagram s'est déroulée début 2012. Nous sommes en 2019 maintenant, il est plus possible que jamais de construire quelque chose de significatif avec une petite équipe d'ingénieurs voire une seule personne.
Si vous n'avez pas encore utilisé Listen Notes, essayez-le maintenant :
Aperçu
Commençons par les exigences ou les fonctionnalités de ce projet Listen Notes.
Listen Notes offre deux choses aux utilisateurs finaux :
- Un site web ListenNotes.com pour les auditeurs de podcasts. Il fournit un moteur de recherche, une base de données de podcasts, des playlists Listen Later, des Listen Clips qui vous permettent de découper un segment de n'importe quel épisode de podcast, et des Listen Alerts qui vous notifient lorsqu'un mot-clé spécifié est mentionné dans de nouveaux podcasts sur Internet.
- Des API de recherche et de répertoire de podcasts pour les développeurs. Nous devons suivre l'utilisation de l'API, recevoir de l'argent des utilisateurs payants, faire du support client, et plus encore.
Je fais tourner tout sur AWS. Il y a 20 serveurs de production (au 5 mai 2019) :
Les serveurs qui font tourner Listen Notes
Vous pouvez facilement deviner ce que fait chaque serveur à partir du nom d'hôte.
- production-web sert le trafic web pour ListenNotes.com.
- production-api sert le trafic API. Nous exécutons deux versions de l'API (au 4 mai 2019), ainsi v1api (la version héritée) et v2api (la nouvelle version).
- production-db exécute PostgreSQL (primaire et réplica)
- production-es exécute un cluster Elasticsearch.
- production-worker exécute des tâches de traitement hors ligne pour maintenir la base de données de podcasts toujours à jour et pour fournir certaines fonctionnalités magiques (par exemple, classement des résultats de recherche, recommandations d'épisodes/podcasts ).
- production-lb est le répartiteur de charge. J'exécute également Redis & RabbitMQ sur ce serveur, par commodité. Je sais que ce n'est pas idéal. Mais je ne suis pas une personne parfaite :)
- production-pangu est le serveur de type production que j'utilise parfois pour exécuter des scripts ponctuels et tester des changements. Quelle est la signification de pangu ?
La plupart de ces serveurs peuvent être mis à l'échelle horizontalement. C'est pourquoi je les nomme production-something1, production-something2 . Il pourrait être très facile d'ajouter production-something3 et production-something4 à la flotte.
Backend
L'ensemble du backend est écrit en Django / Python3. Le système d'exploitation choisi est Ubuntu.
J'utilise uWSGI pour servir le trafic web. Je place NGINX devant les processus uWSGI, qui sert également de répartiteur de charge.
Le principal stockage de données est PostgreSQL, avec lequel j'ai une grande expérience de développement et d'exploitation sur de nombreuses années une technologie testée en conditions réelles est bonne, donc je peux dormir tranquillement la nuit. Redis est utilisé à diverses fins (par exemple, cache, statistiques, ). Il n'est pas difficile de deviner que Elasticsearch est utilisé quelque part. Oui, j'utilise Elasticsearch pour indexer les podcasts et les épisodes et pour servir les requêtes de recherche, tout comme la plupart des entreprises ennuyeuses.
Celery est utilisé pour le traitement hors ligne. Et Celery Beat est utilisé pour planifier les tâches, ce qui est similaire aux tâches Cron mais un peu plus agréable. Si à l'avenir Listen Notes gagne en traction et que Celery & Beat causent des problèmes de mise à l'échelle, je passerai probablement aux deux projets que j'ai réalisés pour mon ancien employeur : ndkale et ndscheduler.
Supervisord est utilisé pour la gestion des processus sur chaque serveur.
Attendez, qu'en est-il de Docker / Kubernetes / serverless ? Non. Avec l'expérience, vous savez quand ne pas sur-ingénieriser. J'ai en fait fait quelques travaux précoces sur Docker pour mon ancien employeur en 2014, ce qui était bien pour une startup d'un milliard de dollars de taille moyenne mais peut être excessif pour une startup minuscule à une seule personne.
Frontend
Le frontend web est principalement construit avec React + Redux + Webpack + ES. Cela est assez standard de nos jours. Lors du déploiement en production, les bundles JS sont téléchargés sur Amazon S3 et servis via CloudFront.
Sur ListenNotes.com, la plupart des pages web sont rendues à moitié côté serveur (Django template) et à moitié côté client (React). La partie rendue côté serveur fournit un modèle de base d'une page web, et la partie rendue côté client est essentiellement une application web interactive. Mais quelques pages web sont rendues entièrement côté serveur, en raison de ma paresse à rendre les choses parfaites et de certains avantages potentiels pour le SEO.
Lecteur audio
J'utilise une version fortement modifiée de react-media-player pour construire le lecteur audio sur ListenNotes.com, qui est utilisé à plusieurs endroits, y compris Listen Notes Website, Twitter embedded player, et le lecteur intégré sur les sites web tiers :
Lecteur intégré sur les sites web tiers
API Podcast
Nous fournissons une API podcast simple et fiable aux développeurs. Construire l'API est similaire à construire le site web. J'utilise la même pile Django/Python pour le backend, et ReactJs pour le frontend (par exemple, tableau de bord de l'API, documentation ).
Tableau de bord de l'API Listen
Documentation de l'API Listen
Pour l'API, nous devons suivre combien de requêtes un utilisateur utilise dans le cycle de facturation actuel, et facturer $$$ à la fin d'un cycle de facturation. Il n'est pas difficile d'imaginer que Redis est largement utilisé ici :)
DevOps
Approvisionnement des machines et déploiement du code
J'utilise Ansible pour l'approvisionnement des machines. Basiquement, j'ai écrit un ensemble de fichiers yaml pour spécifier quel type de serveurs doit avoir quels fichiers de configuration et quel logiciel. Je peux lancer un serveur avec tous les fichiers de configuration corrects et tous les logiciels installés avec un seul bouton. Voici la structure de répertoire de ces fichiers yaml Ansible :
J'aurais pu faire un meilleur travail dans le nommage des choses. Mais encore une fois, c'est suffisamment bon pour maintenant.
J'utilise également Ansible pour déployer le code en production. Basiquement, j'ai un script wrapper deploy.sh qui est exécuté sur macOS :
./deploy.sh production HEAD web
Le script deploy.sh prend trois arguments :
- Environnement : production ou staging.
- Version du dépôt listennotes : HEAD signifie juste déployer la dernière version. Si un SHA d'un commit git est spécifié, alors il déployera une version spécifique du code , ce qui est particulièrement utile lorsque je dois revenir en arrière après un mauvais déploiement.
- Type de serveurs : web, worker, api, ou all. Je n'ai pas besoin de déployer sur tous les serveurs en même temps. Parfois, je fais des changements sur le code Javascript, puis je dois juste déployer sur le web, sans toucher à l'API ou au worker.
Le processus de déploiement est principalement orchestré par des fichiers yaml Ansible, et bien sûr, c'est très simple :
- Sur mon Macbook Pro, si c'est pour déployer sur les serveurs web, alors construire les bundles Javascript et les télécharger sur S3.
- Sur les serveurs cibles, cloner le dépôt listennotes dans un dossier nommé avec un horodatage, vérifier la version spécifique, et installer les nouvelles dépendances Python si nécessaire.
- Sur les serveurs cibles, changer le lien symbolique vers le dossier nommé avec l'horodatage ci-dessus et redémarrer les serveurs via supervisorctl.
Comme vous pouvez le voir, je n'utilise pas ces outils CI fantaisistes. Juste des choses très simples qui fonctionnent réellement.
Surveillance et alertes
J'utilise Datadog pour la surveillance et les alertes. J'ai quelques métriques de haut niveau dans un tableau de bord simple. Tout ce que je fais ici est de renforcer ma confiance lorsque je bidouille les serveurs de production.
Tableau de bord Datadog pour Listen Notes, en décembre 2017.
Je connecte Datadog à PagerDuty. Si quelque chose ne va pas, PagerDuty m'enverra des alertes par appel téléphonique et SMS.
J'utilise également Rollbar pour surveiller la santé du code Django, qui attrapera les exceptions inattendues et me notifiera par e-mail et Slack également.
J'utilise beaucoup Slack. Oui, c'est une entreprise à une seule personne, donc je n'utilise pas Slack pour communiquer avec des êtres humains. J'utilise Slack pour surveiller les événements intéressants au niveau de l'application. En plus d'intégrer Datadog et Rollbar avec Slack, j'utilise également Slack incoming webhooks dans le code backend de Listen Notes pour me notifier chaque fois qu'un utilisateur s'inscrit ou effectue certaines actions intéressantes (par exemple, ajouter ou supprimer des choses). C'est une pratique très courante dans les entreprises technologiques. Lorsque vous lisez certains livres sur l'histoire précoce d'Amazon ou de PayPal, vous saurez que les deux entreprises avaient un mécanisme de notification similaire : chaque fois qu'un utilisateur s'inscrivait, il y avait un son de ding pour notifier tout le monde dans le bureau.
Depuis son lancement début 2017, Listen Notes n'a pas eu de panne majeure (> 5 minutes) sauf pour celle-ci. Je suis toujours très prudent et pratique dans ces choses opérationnelles. Les serveurs web sont significativement sur-approvisionnés, au cas où il y aurait un pic énorme dû à des événements de presse ou autre chose.
Développement
Je travaille dans un espace de coworking WeWork à San Francisco. Certaines personnes peuvent se demander pourquoi ne pas simplement travailler de chez soi ou de certains cafés aléatoires. Eh bien, je valorise beaucoup la productivité et je suis prêt à investir de l'argent dans la productivité. Je ne crois pas que passer plus de temps aide au développement logiciel (ou à tout type de travail de connaissance/créativité). Il est rare que je travaille plus de 8 heures par jour (Désolé, les gens 996). Je veux faire compter chaque minute. Ainsi, un beau bureau privé et relativement cher est ce dont j'ai besoin :) Au lieu d'optimiser pour passer plus de temps et économiser de l'argent, j'optimise pour passer moins de temps et gagner de l'argent :)
Mon bureau chez WeWork
J'utilise un MacBook Pro. J'exécute l'infrastructure (presque) identique à l'intérieur de Vagrant + VirtualBox. J'utilise le même ensemble de fichiers yaml Ansible comme décrit ci-dessus pour approvisionner l'environnement de développement à l'intérieur de Vagrant.
Je souscris à la philosophie du dépôt monolithique. Donc il y a un et un seul dépôt listennotes, contenant les scripts DevOps, le code frontend et backend. Ce dépôt listennotes est hébergé en tant que dépôt privé GitHub. Je fais tout le travail de développement sur la branche principale. J'utilise rarement les branches de fonctionnalités.
J'écris du code et exécute les serveurs de développement (Django runserver & webpack dev server) en utilisant PyCharm. Oui, je sais, c'est ennuyeux. Après tout, ce n'est pas Visual Studio Code ou Atom ou quelque autre IDE cool. Mais PyCharm fonctionne très bien pour moi. Je suis old school.
Mon PyCharm
Divers
Il y a un ensemble d'outils et de services utiles que j'utilise pour construire Listen Notes en tant que produit et entreprise :
- iTerm2 et tmux pour les trucs de terminal.
- Notion pour les listes de choses à faire, wiki, prise de notes, documents de conception .
- G Suite pour le compte email @listennotes.com, le calendrier, et autres services Google.
- MailChimp pour envoyer la newsletter mensuelle par email.
- Amazon SES pour envoyer des emails transactionnels et certains emails marketing.
- Gusto pour me payer et payer les contractants qui ne viennent pas d'Upwork.
- Upwork pour trouver des contractants.
- Google Ads Manager pour gérer les annonces de ventes directes et suivre les performances.
- Carbon Ads et BuySellAds pour les annonces de repli.
- Cloudflare pour la gestion DNS, CDN, et pare-feu.
- Zapier et Trello pour rationaliser le flux de travail des interviews de podcasteurs.
- Medium pour le blog de l'entreprise (évidemment).
- Godaddy et Namecheap pour les noms de domaine.
- Stripe pour recevoir de l'argent des utilisateurs (principalement pour l'API).
- Google speech-to-text API pour transcrire les épisodes.
- Kaiser Permanente pour l'assurance santé.
- Stripe Atlas pour incorporer Listen Notes, Inc.
- Clerky pour générer des documents juridiques pour la levée de fonds (SAFE) et l'embauche de contractants qui ne viennent pas d'Upwork.
- Quickbooks pour la comptabilité.
- 1password pour gérer les identifiants de connexion pour des tonnes de services.
- Brex pour la carte de crédit , vous pouvez obtenir des crédits AWS incrémentiels de 5000 $, qui peuvent être appliqués en plus des crédits AWS de WeWork ou Stripe Atlas.
- Bonvoy Business Amex Card , vous pouvez gagner des points Marriott Bonvoy pour des hôtels de luxe et des vols. C'est le meilleur programme de points de carte de crédit pour voyager :)
- Capital One Spark pour le compte courant.
Gardez votre calme et continuez
Comme vous pouvez le voir, nous vivons dans une époque merveilleuse pour démarrer une entreprise. Il existe tant d'outils et de services prêts à l'emploi qui nous font gagner du temps et de l'argent et augmentent notre productivité. Il est plus possible que jamais de construire quelque chose d'utile pour le monde avec une petite équipe (ou même une seule personne), en utilisant une technologie simple et ennuyeuse.
Avec le temps, les entreprises deviennent de plus en plus petites. Vous n'avez pas besoin d'embaucher des tonnes d'employés à temps plein. Vous pouvez embaucher des services (SaaS) et des contractants à la demande pour faire les choses.
La plupart du temps, le plus grand obstacle à la construction et à la livraison de choses est la sur-réflexion. Et si ceci, et si cela. Mon ami, vous n'êtes pas important du tout. Tout le monde est occupé dans sa propre vie. Personne ne se soucie de vous et des choses que vous construisez, jusqu'à ce que vous prouviez que vous méritez l'attention des autres. Même si vous ratez le lancement initial du produit, peu de gens le remarqueront. Pensez grand, commencez petit, agissez vite. Il est absolument acceptable d'utiliser la technologie ennuyeuse et de commencer quelque chose de simple (même laid), tant que vous résolvez réellement des problèmes.
Il y a tellement de personnes de type cargo-cult maintenant. Ignorez les bruits. Gardez votre calme et continuez.
Si vous n'avez pas encore utilisé Listen Notes, essayez-le maintenant :