我的一人互联网公司
译自:https://broadcast.listennotes.com/the-boring-technology-behind-listen-notes-56697c2e347b
看作者如何轻松利用「Django + 其他技术」构建一个商业网站。
简介
Listen Note 是一个播客搜索引擎和数据库。Listen Note 背后的技术其实非常简单无聊,没有使用什么人工智能、深度学习或区块链(任何人说自己使用了人工智能技术,他使用的都不是真正的人工智能)。
播客,也称 PodCast,是一种数字媒体,指一系列的音频、影片、电子电台或文字档以列表形式经互联网发布,然后听众经由电子设备订阅该列表以下载或流当中的电子文件,从而接收内容。
读完这篇文章后,你应该也可以构建一个 Listen Notes 或者很轻松的做一些类似的事情。
你不需要雇很多员工,还记得 Instagram 被 FaceBook 以 10 亿美元收购的事情吗?当时 Instagram 才 13 个员工,而且并非全部都是工程师。
现在比以往任何时候都可能通过一个小型团队 (甚至一个人) 来构建一些有价值有意义的东西。
Listten Notes 概览
Listen Notes 为用户提供了两样东西。
1. 一个网站,地址为:listennotes.com,它提供了一个搜索引擎、一个播客数据库,还提供了稍后再听、播放列表、听播客片段 (它允许你剪辑任何播客界面的一个片段,然后收听) 以及播客监听提醒 (互联网上的新播客中提到了你指定的关键字,它就会通知你) 等功能
2. 为开发者提供了播客搜索与目录的 API,通过 API 可以了解用户的使用情况。
我在 AWS 上运行了 ListenNotes 的所有东西,总共用了 20 台生产服务器 (2019 年 5 月 5 日为止)
从主机名就可以猜出,每个服务器是做什么的
1.production-web (生产网服务器):主要用于提供 listennotes.com 网络流量服务。
2.production-api (生产 api 服务器):主要用于提供 API 服务,目前我运行了两个版本的 API (v1api 遗留版 api 与 v2api 新版 api)
3.production-db (生产数据库):使用 PostgreSQL 构建主从数据库
4.production-es (Elasticsearch 集群):主要负责搜索
5.production-worker (工作者):主要用于运行各种离线任务 (爬取最新的播客),以保持播客数据库始终是最新的,并提供一些其他的小功能。
6.production-lb (负载均衡器):使用了 Redis 与 RabbitMQ 这种简单方式构建(这不是一个理想的方案,但我从来不是一个完美的人)
7.production-pangu (盘古) 用于运行一些一次性脚本以及进行测试的机器 (这里的盘古就是盘古开天地的盘古,中国文化在国外还是很有吸引力的:))
后端
整个后端使用 Django/Python3 编写,操作系统是 Ubuntu。
使用 uWSGI+Nginx 来部署 Django,Nginx 也用来充当负载均衡器 (这其实就是常见的 Ubuntu+uWSGI+Nginx+Django 的部署方案,不了解的,可以搜索一下,可以找到一大堆具体的操作)。
数据库主要使用 PostgreSQL,我对 PostgreSQL 有多年的开发与运营经验,使用的比较好。
Redis 用于不同目的,如用于缓存、统计等等
Elasticsearch 负责整个网站的搜索,我使用 Elasticsearch 索引了网站中的播客与剧集,使用方式跟很多无聊的公司一样,没什么可说的。
我使用 Celery 来调度离线任务,用 Supervisord 来对服务器上进程进行管理。
为什么不用 Docker/Kubernetes/Serverless 这些技术?
没有必要,对于中小型公司而言,过度工程化是不好的。实际上,早在 2014 年,我就为我的雇主做过一些 Docker 早期的工作,这对于一个规模达到十亿美元的中型创业公司是一件好事,但对我这种一个人的创业公司,可能就有些过了。
前端
网站的前端主要使用 React+Redux+WebPack+ES 构建,这是现在的标准做法。
当部署到生产环境时,我将 JS 包导出到 Amazon S3 上,并通过 CloudFront 提供 CDN 服务
Amazon CloudFront 是由亚马逊网络服务系统提供基础服务的一个内容分发网络(CDN)。其在欧洲、亚洲、北美、澳洲、南美、美国多个主要大城市多地拥有自己的数据中心,共 107 个网络边际服务点提供服务。
在 listennotes.com 这个网站上,大多数网页一半使用了 Django 模块一半使用了 React 程序。服务器渲染部分提供了 web 页面的样板,而客户端 (浏览器端) 部分基本上就是一个交互式 web 应用程序。
但有一些网页是完全同 Django 模板渲染呈现的,因为我懒得将事情做得太完美,而且这可能对 SEO 有一些好处。
音乐播放器
在 listennotes 网站上,我使用一个经过大量修改的开源音乐播放器 react-media-player,这个播放器我使用在了多个地方,通过 iframe 简单嵌入在需要的页面就好了,非常简单。
react-media-player 开源地址:https://github.com/souporserious/react-media-player
播客 API
listennotes 为开发者提供了简单可靠的播客 API,构建 API 类似于构建网站,后端使用了 Django/Python 来构建,前端使用了 ReactJS,效果如下。
对于 API,我们需要跟踪记录使用 API 的用户在当前计费周期中使用了多少次请求,并在计费周期结束时收取相应的费用。
DevOps
机器配置与代码部署
我使用 Ansible 进行服务器的部署,简单来说就写了一堆 yaml 文件来指定什么类型的服务器需要声明什么配置文件以及什么软件,下面是这些 Ansible yaml 文件的目录结构。
我还使用 Ansible 将代码部署到生产环境汇总,基本上,我就在 MacOS 中运行一个部署脚本 deploy.sh 就可以了。
Ansible:做 Python 运维必须知道的一个第三方库,简单而言,Ansible 是一个简便的 IT 自动化引擎,有兴趣可以自行搜索了解一下,其生态丰富,有很多文档可以参考。
deploy.sh 接收 3 个参数,使用方式如下:
./deploy.sh production HEAD web
1.Envireonment:用于区分你要部署的是生产环境还是 staging 环境
2.listennotes repo 版本:HEAD 是只部署最新的版本,如果指定的是 git commite 中的 SHA,那么它就会部署一个特定的版本,这在我需要从一个错误部署中回滚到某个版本的代码来说非常有用。
3.Server kind 服务器类型:有 web、woker、api 等不同服务器类型选择,我不需要同时部署所有的服务器,有时我对 JavaScript 代码进行了修改,我就只需要将其部署到 web 上,而不需要改动 api 与 worker 类型服务器
staging 环境:通常一个 web 项目都需要一个 staging 环境,一来给客户做演示,二来可以作为 production server 的一个 “预演”,正式发布新功能前能及早发现问题。
部署的大部分过程由 Ansible yaml 配置文件精心安排,Ansible 会自动去执行完这个流程,当然,这非常简单:
1. 在我的 MacBook Pro 上:如果要部署到 web 服务器上,就自动构建 JavaScript 包,并上传到 Amazon S3 上
2. 在目标服务器上:通 git,将对应的 listennotes repo 克隆到一个以时间戳命名的文件夹中,检查特定的版本,并通过 pip 安装新的 Python 依赖
3. 在目标服务器上:将软连接 (通过 ln 命令构建软连接) 指向新的时间戳文件夹,并通过 supervisorctl 重启服务器
整个工作我没有使用任何复杂的技术,只是利用了一些简单且实际的技术来实现这样的流程。
监控与报警
我使用 DataDog 服务进行监控与报警,它是一个 SaaS 服务,所以我并不需要做什么复杂的事情就可以得到一个简单仪表盘,并从中看到我服务器的各种指标。
我将 DataDog 链接到 PagerDuty,如果出了什么问题,PagerDuty 会通过电话与短信的形式提醒我。
此外,我还使用 Rollbar 来关注 Django 代码的状况,它会捕捉代码意外产生的异常并通过 email 或 Slack (Slack 基于云的专有即时消息传递平台) 来通知我。
Datadog 是云服务应用程序的监控服务,通过基于 SaaS 的数据分析平台提供对服务器,数据库,工具和服务的监控。PagerDuty 是一家美国云计算公司为 IT 部门提供 SaaS 事件的响应平台。Rollbar 可以自动化错误监视和筛选,开发人员可以在几分钟内修复重要的错误,并且可以快速、轻松地构建软件。这些都是 SaaS 服务,都是要花钱的:(
我个人经常使用 Slack,但公司只有我一个人,所以我不使用 Slack 与他人交流,而是通过 Slack 来监控有趣的应用程序级事件。
除了将 DataDog 和 Rollbar 与 Slack 集成,我还在 Listen Notes 后端代码中使用了 Slack 传入 webhooks (网页钩子),当用户注册或执行一些操作时,Slack 就可以通知到我。
在 2017 年初推出 ListeNote 以来,只在 2018 年 4 月 22 日停电事故宕机了一次,那一次 ListenNote 网站关闭了 4 个小时,我损失了 10 个小时的生产数据,是一次重大的打击。此外 ListeNote 就没有出现过任何中断。
发展
我在旧金山的 WeWork 共享空间工作。
为什么不在家里?
我非常重视生产力,我愿意在生产力上投资,我不认为在家里摸鱼有助于软件开发 (或任何类型的知识 / 创造性工作)。我很少一天工作超过 8 小时,我珍惜每一分钟。
因此,我需要一个漂亮且相对昂贵的私人办公室,我不愿花更多时间来节省这些钱,而更愿意花费一些钱利用更少的时间来赚钱。
我使用 MacBook Pro 进行开发工作,我在 Vagrant+VirtualBox 中运行了几乎与线上相同的环境,我同样使用 Anserable yaml 文件来部署 Vagrant 内部开发环境。
我将 listennote 的代码都托管到 Github 的私有 repo 中,我在主分支上做所有的开发工作,我很少使用功能分支。
我使用 PyCharm 编写并运行 dev 服务 (Django runserver 和 webpack dev server),这很无聊... 我没有使用 VS Code 或 Atom 或其他很酷的 IDE。
保持冷静,持续行动
正如你所见,我们生活在可以轻松创办公司的美好时代,有那么多现成的工具与服务,可以节省我们的时间和金钱,并提高我们的生产力,现在比以往任何时候都更能让一个小团队或一个人利用一些简单且无聊的技术来构建一些对世界有用的东西。
随着时间的推移,公司会越变越小,你不需要雇佣全职员工,你完全可以通过 SaaS 以及 Upwork 上找承包商来完成工作。
大多数时候,阻碍我们行动的就是过度思考,你会想,如果这个... 如果那个...,其实你一点都不重要,每个人都在忙于自己的生活,没人关注你创建的东西,除非你证明你值得被别人关注。即使你完全搞砸了最初的产品发布,也很少有人会注意到。
Think big, start small, act fast.
使用一下无聊的技术开始做一些简单的事情是完全可以的,只要你能真正解决问题。
尾
国内很多文章都将做个东西描绘的复杂难懂,细节很多,而国外很多文章一上来就会说,这是个简单且无聊的东西,我更喜欢国外文章的氛围,不是说,技术一定都很简单,而是给人树立信息,对自己可以做的事情有信心是很好的事情。
如果我的文章对你有所帮助,请点一下「好看」,这对我这个小号而言非常重要,叩谢豪恩。