創(chuàng)建一家互聯(lián)網(wǎng)公司需要幾個(gè)人?一個(gè)就夠了
創(chuàng)建一個(gè)互聯(lián)網(wǎng)公司需要幾個(gè)人?一位來(lái)自舊金山的軟件工程師告訴我們:一個(gè)就夠了。這位工程師創(chuàng)建了一個(gè)名為「Listen Notes」的播客搜索引擎,像谷歌一樣可以方便地搜索海量播客資源。在這篇文章中,這位工程師向我們介紹了他創(chuàng)建「Listen Notes」用到的各種「無(wú)聊」技術(shù)。
Listen Notes 地址:https://www.listennotes.com/
Listen Notes 是一個(gè)播客搜索引擎和數(shù)據(jù)庫(kù)。而 Listen Notes 背后的技術(shù)實(shí)際上毫無(wú)新意。沒(méi)有 AI,沒(méi)有深度學(xué)習(xí),沒(méi)有區(qū)塊鏈?!溉魏握f(shuō)我必須使用 AI 的人都沒(méi)有使用真正的 AI」,文章作者這樣表示。
作者在前言中說(shuō):「閱讀完本文后,讀者應(yīng)該能夠復(fù)制我為 Listen Notes 構(gòu)建的內(nèi)容,或者輕松地實(shí)現(xiàn)類(lèi)似的操作。你無(wú)需聘請(qǐng)很多工程師。請(qǐng)記住,當(dāng) Instagram 融了 5750 萬(wàn)美元并被 Facebook 以 10 億美元收購(gòu)時(shí),他們只有 13 名員工——而且并非所有人都是工程師。Instagram 的故事發(fā)生在 2012 年初?,F(xiàn)在是 2019 年了,一個(gè)小型工程團(tuán)隊(duì)甚至一個(gè)人創(chuàng)造一些有意義的東西比以往任何時(shí)候都有可能。」
這篇介紹了用很多「無(wú)聊」技術(shù)創(chuàng)建互聯(lián)網(wǎng)產(chǎn)品的文章引起了很多網(wǎng)友的討論,有人表示,技術(shù)本身就是一種手段,如果能夠很好地實(shí)現(xiàn)產(chǎn)品的功能,即使是「無(wú)聊」的技術(shù)也會(huì)很棒。
也有網(wǎng)友表示,能夠一個(gè)人同時(shí)掌握前端、數(shù)據(jù)庫(kù)、搜索引擎、存儲(chǔ)、集群、開(kāi)發(fā)、源控制和權(quán)限管理等很多技術(shù)是非常難得的。
在下文中,作者從前端、后端、API 等幾個(gè)角度介紹了自己用到的技術(shù)細(xì)節(jié)。
概述
讓我們從 Listen Notes 項(xiàng)目的需求和功能說(shuō)起。
Listen Notes 為終端用戶(hù)做了兩件事:
- 為播客聽(tīng)眾提供了網(wǎng)站 ListenNotes.com。該網(wǎng)站可以提供搜索引擎、播客數(shù)據(jù)庫(kù)、「稍后聽(tīng)」播放列表、音頻剪輯以及「收聽(tīng)提醒」(當(dāng)新播客中提及指定的關(guān)鍵字時(shí),它會(huì)通知你)。
- 開(kāi)發(fā)人員的播客搜索和目錄 API。我們需要跟蹤 API 使用情況,從付費(fèi)用戶(hù)處獲取資金,進(jìn)行客戶(hù)支持等等。
一切都在 AWS 上運(yùn)行。截至 2019 年 5 月 5 日有 20 臺(tái)服務(wù)器在工作:
運(yùn)行 Listen Notes 的服務(wù)器。
讀者可以通過(guò)主機(jī)名輕松猜出每個(gè)服務(wù)器的任務(wù)。
- production-web 為 ListenNotes.com 提供網(wǎng)絡(luò)流量。
- production-api 提供 api 流量。我們運(yùn)行兩個(gè)版本的 API(截至 2019 年 5 月 4 日),即 v1api(舊版本)和 v2api(新版本)。
- production-db 運(yùn)行 PostgreSQL(主服務(wù)器和副服務(wù)器)
- production-es 運(yùn)行 Elasticsearch 集群。
- production-worker 運(yùn)行離線處理任務(wù),以使播客數(shù)據(jù)庫(kù)始終保持最新?tīng)顟B(tài),并提供一些神奇功能(例如搜索結(jié)果排名、劇集/播客推薦......)。
- production-lb 是負(fù)載均衡器。為方便起見(jiàn),我還在這臺(tái)服務(wù)器上運(yùn)行 Redis 和 RabbitMQ。我知道這不是最理想的方案。反正我不是完美的人:)
- production-pangu 是類(lèi)似生產(chǎn)的服務(wù)器,我有時(shí)會(huì)運(yùn)行一次性腳本和測(cè)試更改。那「pangu」是什么意思?請(qǐng)自行搜索。
這些服務(wù)器大多數(shù)都可以水平擴(kuò)展。這就是為什么我將它們命名為 production-something1,production-something2 ...... 將 production-something3 和 production-something4 再加入其中就非常容易了。
后端
整個(gè)后端是用 Django/Python3 編寫(xiě)的。操作系統(tǒng)是 Ubuntu。
使用 uWSGI 來(lái)提供網(wǎng)絡(luò)流量。NGINX 放在 uWSGI 進(jìn)程前面充當(dāng)負(fù)載均衡器。
主要數(shù)據(jù)存儲(chǔ)是 PostgreSQL,我有多年開(kāi)發(fā)和運(yùn)營(yíng)經(jīng)驗(yàn)——經(jīng)過(guò)測(cè)試的技術(shù)很完善,所以我晚上能睡得著覺(jué)。Redis 用于緩存、統(tǒng)計(jì)數(shù)據(jù)等多個(gè)地方。Elasticsearch 用來(lái)索引播客和劇集并提供搜索查詢(xún),就像大多數(shù)無(wú)聊的企業(yè)一樣。
Celery 用于離線處理。而 Celery Beat 用于調(diào)度任務(wù),類(lèi)似于 Cron 作業(yè),但性能更佳。如果將來(lái) Listen Notes 越來(lái)越受歡迎并且 Celery&Beat 導(dǎo)致一些擴(kuò)展問(wèn)題,我可能會(huì)轉(zhuǎn)向我為前雇主做的兩個(gè)項(xiàng)目:ndkale 和 ndscheduler。
Supervisord 用于每臺(tái)服務(wù)器上的進(jìn)程管理。
那 Docker / Kubernetes / serverless 怎么樣?不。隨著經(jīng)驗(yàn)積累,你就會(huì)知道什么時(shí)候不要過(guò)度設(shè)計(jì)。實(shí)際上,我在 2014 年為我的前雇主做過(guò)一些早期的 Docker 工作,這對(duì)于一家市值十億美元的中等規(guī)模創(chuàng)業(yè)公司來(lái)說(shuō)是件好事,但對(duì)于一個(gè)小型創(chuàng)業(yè)公司來(lái)說(shuō)可能有點(diǎn)「大炮打蚊子」了。
前端
網(wǎng)頁(yè)前端主要使用 React+Redux+Webpack+ES。這是非常標(biāo)準(zhǔn)的。在部署到生產(chǎn)時(shí),JS 包將上傳到 Amazon S3 并通過(guò) CloudFront 提供服務(wù)。
在 ListenNotes.com 上,大多數(shù)網(wǎng)頁(yè)都是半服務(wù)器端呈現(xiàn)(Django 模板)和半客戶(hù)端呈現(xiàn)(React)。服務(wù)器端呈現(xiàn)部分提供網(wǎng)頁(yè)的樣板,客戶(hù)端呈現(xiàn)部分基本上是交互式網(wǎng)頁(yè)應(yīng)用程序。但是一些網(wǎng)頁(yè)完全通過(guò)服務(wù)器端呈現(xiàn),因?yàn)槲业膽卸枋故虑樽兊猛昝酪约俺霈F(xiàn)一些潛在的 SEO 優(yōu)勢(shì)。
音頻播放器
我使用了一個(gè)經(jīng)過(guò)大量修改的 react-media-player 在 ListenNotes.com 上構(gòu)建音頻播放器,該播放器應(yīng)用在 Listen Notes 網(wǎng)站、Twitter 嵌入式播放器和第三方網(wǎng)站上的嵌入式播放器中:
第三方網(wǎng)站上的嵌入式播放器。
播客 API
我們?yōu)殚_(kāi)發(fā)人員提供簡(jiǎn)單可靠的播客 API。構(gòu)建 API 類(lèi)似于構(gòu)建網(wǎng)站。在后端使用相同的 Django/Python 堆棧,前端使用相同的 ReactJs(例如 API Dashboard、文檔......)。
ListenNotes 的 API dashboard。
ListenNotes 的 API 文檔。
對(duì)于 API,我們需要追蹤用戶(hù)在當(dāng)前計(jì)費(fèi)周期中使用的請(qǐng)求數(shù)量,并在周期結(jié)束時(shí)收取費(fèi)用。不難想象,Redis 在這里被大量使用:)
DevOps
機(jī)器配置和代碼部署
我使用 Ansible 進(jìn)行機(jī)器配置?;旧?,我寫(xiě)了一堆 yaml 文件來(lái)指定需要什么類(lèi)型的服務(wù)器、什么配置文件和什么軟件。我可以用所有正確的配置文件和軟件啟動(dòng)一個(gè)服務(wù)器,并通過(guò)「一鍵安裝」完成安裝。這是 Ansible yaml 文件的目錄結(jié)構(gòu):
我可以在命名方面做得更好。但現(xiàn)在已經(jīng)足夠好了。
我還使用 Ansible 將代碼部署到生產(chǎn)環(huán)境中?;旧?,我有一個(gè)在 macOS 上運(yùn)行的打包腳本 deploy.sh:
- ./deploy.sh production HEAD web
deploy.sh 腳本有三個(gè)參數(shù):
- 環(huán)境:生產(chǎn)或分段;
- listennotes repo 版本:HEAD 表示「僅部署最新版本」。如果指定了 git commit 的 SHA,那么它將部署特定版本的代碼——當(dāng)我需要從錯(cuò)誤的部署撤回時(shí),這特別有用;
- 服務(wù)器類(lèi)型:web、worker、api 或所有服務(wù)器。我不必一次部署到所有服務(wù)器。有時(shí)我會(huì)對(duì) Javascript 代碼進(jìn)行修改,然后我只需要部署到 Web,而無(wú)需涉及 api 或 worker。
部署過(guò)程主要由 Ansible yaml 文件制定,當(dāng)然,它很簡(jiǎn)單:
- 在 Macbook Pro 上,如果要部署到 Web 服務(wù)器,則構(gòu)建 Javascript 包并上傳到 S3;
- 在目標(biāo)服務(wù)器上,git 將 listennotes repo 克隆到一個(gè)以時(shí)間戳命名的文件夾,檢查特定版本,然后安裝新的 Python 依賴(lài)項(xiàng)(如果有的話(huà));
- 在目標(biāo)服務(wù)器上,將符號(hào)鏈接切換到上述時(shí)間戳命名文件夾,并通過(guò) supervisorctl 重新啟動(dòng)服務(wù)器。
我不使用那些花哨的 CI 工具。實(shí)際的操作非常簡(jiǎn)易。
監(jiān)控和警報(bào)
我使用 Datadog 進(jìn)行監(jiān)控和警報(bào)。我在一個(gè)簡(jiǎn)單的監(jiān)控界面中有一些高級(jí)指標(biāo)。這里所做的一切都是為了在弄亂生產(chǎn)服務(wù)器時(shí)增強(qiáng)信心。
適用于 Listen Notes 的 Datadog 監(jiān)控界面(截至 2017 年 12 月)。
我將 Datadog 連接到 PagerDuty。如果出現(xiàn)問(wèn)題,PagerDuty 將通過(guò)電話(huà)和短信向我發(fā)送提醒。
我還使用 Rollbar 來(lái)監(jiān)控 Django 代碼的運(yùn)行狀況,它會(huì)捕捉異常,并通過(guò)電子郵件和 Slack 通知我。
我經(jīng)常使用 Slack。這是個(gè)一個(gè)人的公司,所以我不使用 Slack 與人交流。我使用 Slack 來(lái)監(jiān)視有趣的應(yīng)用級(jí)事件。除了將 Datadog 和 Rollbar 與 Slack 集成之外,我還在 Listen Notes 后端代碼中使用 Slack 傳入 webhooks,以便在用戶(hù)注冊(cè)或執(zhí)行一些操作(例如添加或刪除內(nèi)容)時(shí)通知我。這是科技公司常用的做法。當(dāng)你閱讀亞馬遜或 PayPal 早期發(fā)展的一些書(shū)籍時(shí),你會(huì)發(fā)現(xiàn)兩家公司都有類(lèi)似的通知機(jī)制:每當(dāng)用戶(hù)注冊(cè)時(shí),都會(huì)有「?!沟穆曇敉ㄖk公室中的每個(gè)人。
自 2017 年初推出以來(lái),Listen Notes 只出現(xiàn)過(guò)一次長(zhǎng)時(shí)崩潰(大于 5 分鐘)。在這些操作方面,我總是非常謹(jǐn)慎和務(wù)實(shí)。網(wǎng)絡(luò)服務(wù)器顯著過(guò)剩,是為了防止某個(gè)新聞事件或其他因素導(dǎo)致流量飆升。
開(kāi)發(fā)
我在舊金山的 WeWork 共享空間工作。有些人可能想知道為什么不在家里或咖啡店工作。那是因?yàn)槲曳浅V匾曅剩以敢庠谛噬贤顿Y。我不相信堆砌時(shí)間就能開(kāi)發(fā)出好軟件。我很少一天工作超過(guò) 8 小時(shí)(對(duì)不起了,996 的朋友)。我想把每一分鐘都花得有意義。因此,我需要一個(gè)精致且相對(duì)昂貴的私人辦公室:) 與其為了省錢(qián)花更多時(shí)間,我選擇花費(fèi)更少的時(shí)間去賺錢(qián):)
我在 WeWork 的辦公室。
我用的電腦是 MacBook Pro。我在 Vagrant+ VirtualBox 中運(yùn)行(幾乎)相同的基礎(chǔ)架構(gòu)。我使用與上述相同的 Ansible yaml 文件集在 Vagrant 中配置開(kāi)發(fā)環(huán)境。
我贊同 monorepo 理念。因此,我只有一個(gè) listennotes repo,包含 DevOps 腳本、前端和后端代碼。這個(gè) listennotes repo 是作為 GitHub 私人 repo 托管。我在主分支上做所有的開(kāi)發(fā)工作。我很少使用功能分支。
我使用 PyCharm 編寫(xiě)代碼并運(yùn)行 dev 服務(wù)器(Django runserver 和 webpack dev server)。我知道這很無(wú)聊。畢竟它不是 Visual Studio Code、Atom 或 IDE。但 PyCharm 對(duì)我來(lái)說(shuō)效果很好。畢竟我很老派。
我的 PyCharm。
其他
我使用許多有用的工具和服務(wù)將 Listen Notes 打造為一款產(chǎn)品和一個(gè)公司:
- iTerm2 和 tmux 用于獲取終端內(nèi)容。
- Notion 用于 TODO 列表、維基、記筆記和設(shè)計(jì)文檔......
- G Suite 用于 @listennotes.com 電子郵件帳戶(hù)、日歷和其他 Google 服務(wù)。
- MailChimp 發(fā)送每月電子郵件簡(jiǎn)報(bào)。
- Amazon SES 用于發(fā)送交易郵件和營(yíng)銷(xiāo)郵件。
- Gusto 用于支付自己和非 Upwork 承包人的工資。
- Upwork 用于尋找承包人。
- Google Ads Manager 管理直銷(xiāo)廣告并跟蹤績(jī)效。
- Carbon Ads 和 BuySellAds 用于備用廣告。
- Cloudflare 用于 DNS 管理、CDN 和防火墻。
- Zapier 和 Trello 簡(jiǎn)化了播客工作流程。
- Medium 是公司博客的媒介。
- Godaddy 和 Namecheap 用于域名。
- Stripe 用于從用戶(hù)處獲取資金(主要用于 API)。
- Google speech-to-text API 用于語(yǔ)音轉(zhuǎn)換。
- Kaiser Permanente 用于健康保險(xiǎn)。
- Stripe Atlas 用于合并 Listen Notes Inc。
- Clerky 為融資(SAFE)和雇傭非 Upwork 承包人生成法律文件。
- Quickbooks 用于記賬。
- 1password 用于管理大量服務(wù)的登錄憑證。
- Brex 用于信用卡,還可以獲得額外$ 5,000 AWS 積分,可以在 WeWork 或 Stripe Atlas 的 AWS 積分上應(yīng)用。
- Bonvoy Business Amex 卡——可以獲得豪華酒店和航班的 Marriott Bonvoy 積分。這是旅行的最佳信用卡積分:)
- Capital One Spark 用于支票賬戶(hù)。
膽大心細(xì),馬上行動(dòng)
如你所見(jiàn),我們生活在一個(gè)創(chuàng)業(yè)的黃金時(shí)代。有許多現(xiàn)成的工具和服務(wù)可以節(jié)省我們的時(shí)間和金錢(qián),提高我們的生產(chǎn)力。使用簡(jiǎn)單而枯燥的技術(shù),以一己之力(或一個(gè)團(tuán)隊(duì))創(chuàng)造對(duì)世界有用的東西比以往任何時(shí)候都更有可能。
隨著時(shí)間的推移,公司會(huì)變得越來(lái)越小。你無(wú)需雇傭大量的全職員工。你可以通過(guò)購(gòu)買(mǎi)服務(wù)或外包來(lái)完成工作。
大多數(shù)時(shí)候,創(chuàng)造和傳播的最大障礙是想太多。這怎么辦?那怎么辦?孩子,你把自己看太重了。每個(gè)人都忙于自己的生活。沒(méi)有人關(guān)心你和你創(chuàng)建的東西,直到你證明你值得別人關(guān)注。即使你搞砸了最初的產(chǎn)品,也很少有人會(huì)注意到?!负暧^思維,細(xì)節(jié)到位,迅速反應(yīng)!」只要你真正解決了問(wèn)題,就算使用無(wú)聊的技術(shù)完成簡(jiǎn)單(甚至簡(jiǎn)陋)的任務(wù)也完全沒(méi)問(wèn)題。