2024 年 9 月 27 日星期五

Rails 8.0 Beta 1: 无需 PaaS

作者:dhh

部署现代 Web 应用程序(配备了快速、安全和易于更新所需的一切)变得如此困难,以至于许多开发人员不敢在没有 PaaS(平台即服务)的情况下进行部署。但这太荒谬了。没有人应该为了让部署变得友好和可用而不得不为基本计算付出高得多的价格。这是开源的任务,Rails 已经准备好解决这个问题。

这是我在 Rails World 大会上的主题演讲 的前提,也是 Rails 8 的目标。因此,我们很高兴在此发布这个新版本的第一个 Beta 版本,与多伦多的 Rails World 大会一起庆祝。

虽然是 Beta 版本,但其中包含的绝大多数内容都经过了充分的实战测试。Rails 非常幸运,拥有像 ShopifyGitHub 这样的大型应用程序,以及各种规模的其他应用程序,都直接运行在框架的最前沿,确保尽早发现问题。

此外,所有新的部署工具以及 Solid Cache 和 Solid Queue 已经在 37signals 的云迁移项目 中为 Basecamp 和 HEY 等应用程序服务超过 18 个月。

尽管如此,新事物总是会有一些问题,如果您愿意在最终版本发布之前将您的应用程序升级到 Rails 8,帮助我们找出这些问题,我们将不胜感激。让我们一起让这个版本尽可能 SOLID!

以下是所有主要的新功能:

Kamal 2 + Thruster

Rails 8 预先配置了 Kamal 2,用于将您的应用程序部署到任何地方。无论是在云虚拟机上还是您自己的硬件上。Kamal 可以将一个新的 Linux 系统变成一个应用程序或附件服务器,只需一个“kamal setup”命令。它只需要一组服务器的 IP 地址以及您已存放的 SSH 密钥,您就可以在两分钟内进入生产环境。

Kamal 可以如此轻松地做到这一点,因为 Rails 已经包含了一个高效且经过优化的 Dockerfile,用于将您的应用程序开箱即用地转换为一个生产就绪的容器镜像。您只需要提供自己的容器注册表帐户,例如 Docker Hub 或 GitHub,用于存储镜像。

在 Rails 8 中,这个 Dockerfile 已经升级,包括一个名为 Thruster 的新代理,它位于 Puma Web 服务器之前,提供 X-Sendfile 加速、资产缓存和资产压缩。这意味着无需在前面放置 Nginx 或任何其他 Web 服务器。默认的 Rails 容器已准备好立即接收来自互联网的流量。

Kamal 2 还包括一个代理,这次是一个定制的单元,名为 Kamal Proxy,用于替换它在启动时使用的通用 Traefik 选项。这个代理提供超快的零停机时间部署、通过 Let’s Encrypt 自动化的 SSL 证书以及支持在一台服务器上运行多个应用程序,而无需任何复杂的配置。

再加上一项处理秘密的修订策略(具有对 1password、Bitwarden 和 LastPass 的内置集成)以及一个新的别名功能,可以使用“kamal console”等命令启动远程 Rails 控制台会话,它提供了一个完整的软件包,不仅可以处理部署,还可以处理您的应用程序在生产环境中的运行。

Kamal 2 由 Donal McBreen 领导,Kamal Proxy + Thruster 由 Kevin McConnell 创建,他们都来自 37signals

减少依赖

让 Rails 更易于部署的一部分是减少启动所需的其他服务的数量。在过去,Rails 需要 MySQL 或 PostgreSQL 以及 Redis 来充分利用其所有功能,例如作业、缓存和 WebSockets。现在,借助名为 Solid Cable、Solid Cache 和 Solid Queue 的三个新的基于数据库的适配器,所有这些都可以通过 SQLite 完成。

这些适配器都基于同一个前提:磁盘速度已经足够快,我们不需要使用 RAM 来执行很多任务。这使我们能够从 SSD 和 NVMe 驱动器比传统的机械硬盘快几个数量级中获益,从而简化了工作。

Solid Cable

Solid Cable 消除了使用 Redis 作为发布/订阅服务器来中继来自应用程序的 WebSocket 消息到连接到不同进程的客户端的需要。它使用快速轮询,但仍然几乎与 Redis 一样快,当通过同一服务器在 SQLite 上运行时。对于大多数应用程序来说,它已经足够快了。作为一项额外的好处,Solid Cable 默认情况下将发送到数据库中的消息保留一天,这可能有助于调试棘手的实时更新问题。

Solid Cable 由来自 Working Not Working 的 Nick Pezza 创建。

Solid Cache

Solid Cache 消除了使用 Redis 或 Memcached 来存储特定 HTML 片段缓存的需要。除了摆脱其他服务依赖之外,它还通过使用磁盘存储而不是 RAM 存储,实现了更大更便宜的缓存。这意味着您的缓存可以存活更长时间,并涵盖更多请求,甚至可以覆盖第 95 个或第 99 个百分位数。此外,这个缓存可以被加密,并且可以由一个明确的保留期限(例如 30 天或 60 天)管理。使其更容易满足现代隐私政策和期望。

Solid Cache 已经在 Basecamp 中投入生产使用一年多,它存储了 10 TB 的数据,支持 60 天的完整保留窗口,并在引入后将 P95 渲染时间缩短了一半。

Solid Cache 由来自 37signals 的 Donal McBreen 创建。

Solid Queue

Solid Queue 消除了对 Redis 以及单独的作业运行框架(如 Resque、Delayed Job 或 Sidekiq)的需要,适用于大多数人。对于高性能安装,它基于在 PostgreSQL 9.5 中首次引入的新的 FOR UPDATE SKIP LOCKED 机制,但现在也适用于 MySQL 8.0 及更高版本。对于更适度的需求,它也适用于 SQLite,这使得它成为无依赖路径的理想选择,可以立即在生产环境中看到您的工作,并获得第一次 HELLO WORLD 的快乐体验。

Solid Queue 可以作为 puma 插件运行(这是单服务器安装的默认设置),也可以使用新的 bin/jobs 命令启动专用调度程序。可以运行多个调度程序处理专用队列,根据定制的性能调优,所有这些都采用灵活的配置方案,开箱即用,无需调整,但一旦需要,就可以提供所有控制选项。

它几乎拥有您对现代作业排队系统的所有期望功能。包括强大的并发控制、失败重试和警报、定期作业调度等等。在 HEY 中,它取代了至少 6 个不同的 Resque gems,作为唯一的集成解决方案。

Solid Queue 在过去 18 个月里,在真实生产环境的压力下精心开发,今天它每天为 37signals 的 HEY 运行 2000 万个作业。

Solid Queue 由来自 37signals 的 Rosa Gutiérrez 创建。

让 SQLite 准备好投入生产

除了三款 Solid 适配器使 SQLite 能够为 Action Cable、Rails.cache 和 Active Job 提供动力之外,Rails 8 还对 SQLite 适配器和 Ruby 驱动程序进行了大量工作,使其适合在 Rails 8 中用于真正的生产环境。

在 37signals,我们正在构建一个不断增长的应用程序套件,这些应用程序使用 SQLite 在生产环境中运行,例如 ONCE。现在有数千个 CampfireWritebook 安装运行在野外,它们都运行 SQLite。这意味着确保 Rails(和 Ruby)与这个出色的基于文件的数据库一样好地工作,对我们提出了很多实际要求。通过适当的默认值,例如 WAL 和 IMMEDIATE 模式。特别感谢 Stephen Margheim 的 一系列此类改进,以及 Mike Dalessio 的 解决 Ruby 驱动程序中最后一个 SQLite 文件损坏问题

用 Propshaft 替换 Sprockets

但 Rails 8 不仅限于更好的部署故事和基于数据库的适配器。我们还将 Propshaft 作为新的默认资产管道。Propshaft 是 #NOBUILD 作为 Rails 7 默认路径(并将更复杂的 JavaScript 设置卸载到 bun/esbuild/vite/etc)的使命的派生。作为 新的资产管道,它取代了旧的 Sprockets 系统,该系统可以追溯到 2009 年。那时,还没有 JavaScript 编译器和构建管道。很久很久以前,我们无法想象浏览器拥有出色的 JavaScript 实现、导入地图,以及由于 HTTP/2 而不受许多小文件限制。

这是一个很好的例子,说明了偶尔需要重新拿起一张白纸,从第一性原理再次考虑一个熟悉的问题。事实证明,在我们的新 #NOBUILD 世界中,资产管道只需要做两件主要事情:提供资产的加载路径,并用摘要标记它们,以允许远期过期。仅此而已。Sprockets 做了比这多得多的工作,其中很多工作的方式早就过时了,而且已经处于一种缺乏贡献者愿意或能够帮助解决的破败状态。

因此,我们感谢 Sprockets 15 年的贡献,但 Rails 中资产管道的未来被称为 Propshaft。现在它是所有 Rails 8 应用程序的默认值,但我们将继续支持现有应用程序中的 Sprockets。

Propshaft 由来自 37signals 的 David Heinemeier Hansson 和来自 FestaLab 的 Breno Gazzola 创建。

生成身份验证基础

最终,为了更容易进行生产,我们也应该让它更容易安全。Rails 长期以来一直在为优秀身份验证系统的主要组件组装高级抽象,以实现这种便捷性。自 Rails 5 以来,我们一直在使用 has_secure_password,但最近也在 Rails 7.1 中引入了 generates_token_for :password_reset 以及 authenticate_by。现在,在 Rails 8 中,我们把所有部分整合到一个完整的身份验证系统生成器中,它为基于会话、可重置密码、可跟踪元数据的身份验证系统创建了一个很好的起点。

只需运行 bin/rails generate authentication,您将获得 SessionUser 的基本模型,以及一个 PasswordsMailerSessionsController 和一个 Authentication 关注点。您只需要提供一个用户注册流程(因为这些通常是每个应用程序特有的)。无需担心使用这些提供的基础来滚动自己的身份验证设置(或者,天哪,为它付费!)。

以及其他一切

Rails 8 在 Rails 7.2 发布几个月后发布,但除了上面介绍的所有这些令人难以置信的新工具之外,还包含大量修复和改进。Rails 的所有功能从未像现在这样强大。这是一个参与框架的绝佳时机,也是第一次登上我们的列车的绝佳时机。无论您是喜欢 #NOBUILD 还是 #NOPAAS,或者只是被压缩复杂性的任务所吸引,您都将与一个充满热情的构建者社区融洽相处,他们既重视美丽的代码,也重视生产力。