单人SaaS的技术堆栈

2020-11-23 22:41:16

作为一名内心的工程师,每当我看到一家公司撰写有关其技术堆栈的文章时,我都会冲泡一杯新鲜的咖啡,坐下来欣赏新发现的小点心。

了解其他人的业务背后隐藏着一些有趣的东西。就像八卦,但关于软件。

几个月前,我开始从事另一项私有分析服务,该项目经历了无数次迭代,我感到幸运的是,已经有400多个网站与之集成,即使它仍处于早期阶段。

这就是为什么,本着与我用来运行SaaS的杰克·拉扎罗夫(Jake Lazaroff)的工具和服务相同的精神,我认为现在该轮到我来简要编写用于运行此新服务的技术了。

多年来,我在工具带中添加了许多编程语言,但是对于单独项目,我尤其是将两种语言融合在一起,从而在生产率和可靠性之间取得了很好的平衡。

Python:大多数后端代码都在Python中。这使我能够以惊人的速度发布功能。另外,我将mypy用于可选的类型提示,这有助于使代码库易于管理。

打字稿:我以前尽量避免在前端工作。直到大约4年前我发现Typescript。它使整个体验变得更好了,现在我将它与React一起用于我的所有项目。

在我站在已经发布了我所依赖的大量开源代码的巨人的肩膀上时,该列表可能非常庞大。但由于它们在堆栈中的主要作用,我只想强调一下:

Django:对于单独开发人员来说就像一个超级大国。您在该行业中工作的时间越长,就越能避免在第100次重新发明轮子而倍感欣慰。单一框架可以使您真正,真正地受益。对我来说,这是关于可预测的软件,它在所有重要方面都非常快。如果您有兴趣,我会在“选择无聊技术”中讨论更多有关此主题的信息。

React:仪表板的Web应用程序是使用React + Webpack构建的。在长时间使用Angular之后,我切换到React,因为它只是可插拔的视图层,不会妨碍操作。我使用出色的django-react-templatetags将React组件嵌入到我的Django模板中。

NextJS:我将其用于登录页面,文档和您当前正在阅读的博客。它使我能够重用各种React组件,并且仍然获得静态生成的站点的性能和SEO优势。

芹菜:我将其用于任何背景/预定任务。它确实具有针对更高级用例的学习曲线,但是一旦您了解了它的工作原理,并且更重要的是它失败了,它就非常可靠。

Bootstrap 4:我在Bootstrap的顶部构建了一个自定义主题。它节省了我很多时间,并且周围有很多文档。这就是我选择它的原因。

我最初将所有数据存储在一个SQLite数据库中,进行备份意味着将该文件的副本复制到S3之类的对象存储中。当时,对于我测试过Panelbear的小型站点来说,这已经足够了。但是随着我添加更多功能和网站,我需要更多专门的软件来支持这些功能:

Clickhouse:我相信这是随着时间的推移将无处不在的那些技术之一。老实说,这是一款很棒的软件,使我能够构建起初在低成本硬件上似乎无法实现的功能。我确实打算在将来的博客中写一些关于在Kubernetes上运行Clickhouse的经验教训。敬请期待!

PostgreSQL:我的关系数据库。 Sane默认使用,经过测试并与Django深度集成。对于Panelbear,我将其用于与分析无关的所有应用程序数据。对于分析数据,我写了一个简单的界面来查询Django中的Clickhouse。

Redis:我将它用于许多方面:缓存,速率限制,作为任务队列以及作为具有各种功能的TTL的键/值存储。坚如磐石,功能强大的文档。

我将基础设施视为牲畜而不是宠物,服务器和集群之类的东西本该来来往往。因此,如果一台服务器“生病”,我将其替换为另一台。这意味着一切都在git repo中被描述为代码,我不会通过SSH进入服务器来进行更改。您可以将其视为一个模板,用一个命令将我的整个基础架构克隆到任何AWS区域/环境中。

这在灾难恢复时也对我有帮助。我只运行了一些命令,几分钟后,我的堆栈已重新创建。当我从DigitalOcean迁移到Linode,再到最近迁移到AWS时,这特别有用。一切都用代码描述,因此即使在几年后,也很容易跟踪我拥有的组件(所有公司都有一些通过用户界面上的clicky-clicky创建的AWS IAM策略或VPC子网,现在每个人都依赖它)。

Terraform:我使用Terraform管理大部分云基础架构。在我的Terraform清单中声明了诸如EKS集群,S3存储桶,角色和RDS实例之类的东西。状态会同步到加密的S3存储桶,以免在我的开发笔记本电脑发生故障时遇到麻烦。

Docker:我将所有内容构建为Docker映像。甚至有状态组件(如Clickhouse或Redis)也作为Docker容器打包并运送到我的集群中。这也使我的堆栈非常可移植,因为我可以在可以运行Docker的任何地方运行它。

Kubernetes:允许我极大地简化操作方面。但是,我并不会向所有人推荐它,因为多年来我很高兴为雇主解雇了多次生产大火,因此我对使用它感到很自在。我还依靠托管产品,这也有助于减轻负担。

GitHub Actions:过去我通常会使用CircleCI(这也很棒),但是对于这个项目,我更喜欢使用GitHub Actions,因为它删除了另一个需要访问我的存储库和部署机密的服务。但是,CircleCI具有很多好的功能,我仍然推荐它。

我从DigitalOcean的一个月费$ 5的实例开始,然后转向管理型Kubernetes产品,因为我正在彻底改变Kubernetes已经为我提供的许多功能(服务发现,TLS证书,负载平衡,日志循环) ,卷展栏,缩放比例,容错等)。

不幸的是,即使在较大的实例上,DigitalOcean的Kubernetes产品也存在可靠性问题。群集API经常会随机关闭并且不再恢复,这破坏了包括负载均衡器在内的许多群集服务,这对我来说意味着停机。每当发生这种情况时,我都必须创建一个新集群,尽管Terraform使其变得微不足道,但这并没有激发人们对其托管服务的信心。我怀疑他们的控制飞机配置不足,考虑到价格,这是可以理解的。

不幸的是,几周后我无法解决问题。这就是为什么我决定搬到Linode的原因,在接下来的1.5个月的蜜月中,我遇到了0个问题。

但是,由于我收到了一笔非常划算的交易,最近我又一次搬到了AWS。它还使我能够使用RDS等托管服务来减轻对PostgreSQL的管理负担,这是一个很大的优势。使所有这些迁移相对容易的原因是,我的所有基础结构都是通过Terraform和Kubernetes清单进行描述的。迁移主要包括一个晚上,一些茶和耐心。但这是另一篇文章。

AWS:可预测,有很多托管服务。但是,我在全职工作中使用它,因此我不必花费太多时间来解决问题。我使用的主要服务是EKS,ELB,S3,RDS,IAM和专用VPC。将来我可能还会添加Cloudfront和Kinesis。

Cloudflare:我主要将其用于DDoS保护,为DNS服务以及卸载各种静态资产的边缘缓存(目前减少了AWS的80%出口费用-它们的带宽定价太疯狂了!)。

让我们来加密:免费的SSL证书授权。我在Kubernetes集群中使用cert-manager根据我的入口规则自动颁发和更新证书。

Namecheap:我选择的域名注册商。允许MFA登录,这是一项重要的安全功能。与其他注册商不同,他们每隔几年就进行一次昂贵的续签,并不令我感到惊讶。我喜欢他们。

以下组件可以自动完成大部分开发工作。我也使用其他几个,但是我使用的一些主要是:

ingress-nginx:使用NGINX作为反向代理和负载平衡器的Kubernetes坚如磐石的入口控制器。坐在NLB后面,该NLB控制进入群集节点的入口。

Flux:GitOps在Kubernetes中进行连续交付的方式。当我发布新的Docker映像时,基本上会拉动并部署它们。

kubectl:与Kubernetes集群进行交互以查看日志,pod和服务,SSH到正在运行的容器中,等等。

Prometheus:有效存储时间序列数据以进行监视。跟踪所有群集和应用程序指标。这比使用Cloudwatch进行应用程序指标便宜得多。

Grafana:用于Prometheus监控数据的漂亮仪表板。所有仪表板均在JSON文件中描述,并在git repo中进行版本控制。

Sentry:应用程序异常监视和聚合。带有其他元数据的未处理错误时通知。

Loki:受Prometheus启发的日志聚合系统。它与prometheus-operator捆绑在一起,可以帮助我在整个群集中搜索日志。

Sendgrid:我将其用于交易电子邮件(电子邮件验证,登录安全警报,密码重置等)。但是,我注意到许多帐户验证电子邮件都没有发送。他们的IP地址似乎已被多家电子邮件提供商阻止,因此我将来考虑考虑迁移到Postmark。

PyCharm:可能是Python的最佳IDE。我可以轻松地重构和导航整个代码库,而不仅仅是单个文件。即使使用大型动态代码库,效果也很好。

调用:我将所有代码库任务包装在调用的命令中。例如,inv build将准备静态资产,打包前端/后端分发,并生成docker映像。这样,就可以在本地运行与在CI上运行的命令相同的命令。

Panelbear Analytics:当然,有比Panelbear本身更好的工具来跟踪Panelbear的网站分析:)狗食的好处是真实的,因为我是我自己的客户。

健康检查:当计划的作业没有运行时,通过电子邮件/ whatsapp通知我。它也是自举的SaaS,几年前我很高兴将其推荐给我的现任雇主。为他们防止了一些事件,因此它已经物有所值。

Figma:取代了Sketch作为我的入门工具,用于为目标页面快速制作模型,横幅和插图。