2024 年 9 月 27 日,星期五

Rails 8.0 Beta 1:无需 PaaS

由 dhh 发布

部署现代 Web 应用——包含所有必要的措施,以确保其快速、安全且易于更新——变得如此困难,以至于许多开发者不敢在没有 PaaS(平台即服务)的情况下进行部署。但这是荒谬的。没有人应该为基本计算支付高出几个数量级的费用,仅仅是为了让部署变得友好和可用。这是开源的使命,Rails 已准备好解决它。

这就是我在 Rails World 主题演讲中的前提,也是 Rails 8 的使命。因此,我们很高兴在加拿大多伦多举行的 Rails World 上发布这个新版本的第一个 beta 版本,以示庆祝。

尽管这是一个 beta 版本,但其中包含的大部分内容都已经过彻底的实战测试。Rails 独特之处在于拥有 ShopifyGitHub 等大型应用,以及许多其他各种规模的应用,它们都运行在框架的最前沿,以确保及早发现问题。

此外,所有新的部署工具以及 Solid Cache 和 Solid Queue,已经在 37signals 的云迁移过程中运行了 18 个多月,应用于 Basecamp 和 HEY 等应用。

尽管如此,新事物总会有一些问题,我们非常感谢您在最终发布前通过将您的应用程序升级到 Rails 8 来帮助我们找到这些问题。让我们一起让这个版本尽可能地 SOLID!

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

引入 Kamal 2 + Thruster

Rails 8 预装了 Kamal 2,可用于将您的应用程序部署到任何地方。无论是部署到云虚拟机还是您自己的硬件。Kamal 只需一个“kamal setup”命令,即可将一台全新的 Linux 服务器变成一个应用服务器或辅助服务器。它只需要一组服务器的 IP 地址以及您 deposited 的 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 由 37signals 的 Donal McBreen 主导开发,Kamal Proxy + Thruster 则由 37signals 的 Kevin McConnell 创建。

大大减少了依赖

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

这些适配器都基于相同的理念:磁盘速度已足够快,我们可以不需要 RAM 来处理这么多任务。这使我们可以从 SSD 和 NVMe 驱动器比老式旋转式硬盘快几个数量级带来的简化优势中受益。

Solid Cable

Solid Cable 取代了 Redis 作为发布/订阅服务器的需求,用于将 WebSocket 消息从应用程序中继到连接到不同进程的客户端。它使用快速轮询,但在通过相同的服务器在 SQLite 上运行时,其速度几乎与 Redis 一样快。对于大多数应用程序来说,这已经足够快了。此外,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 中,它取代了 no less than 6(!) 不同的 Resque gem,作为一个集成解决方案。

Solid Queue 在过去 18 个月内,在真实的生产环境中承受了巨大的压力,并得到了细致的开发。如今,仅 HEY 每天就运行 2000 万个作业,来自 37signals。

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

为生产环境准备 SQLite

除了使 SQLite 能够支持 Action Cable、Rails.cache 和 Active Job 的 Solid 适配器三件套之外,Rails 8 还为使 SQLite 适配器和 Ruby 驱动程序适用于实际生产环境做了大量工作。

在 37signals,我们正在构建一个不断增长的应用套件,这些应用使用 SQLite 在生产环境中运行,例如 ONCE。现在有数千个 Campfire 和 Writebook 的安装在野外运行,它们都使用 SQLite。这意味着我们需要在确保 Rails(和 Ruby)能够尽可能好地处理那个出色的文件数据库方面承受巨大的实际压力。通过 WAL 和 IMMEDIATE 模式等正确设置。特别感谢 Stephen Margheim 提供了一系列此类改进,以及 Mike Dalessio 解决了 Ruby 驱动程序中一个临时的 SQLite 文件损坏问题

用 Propshaft 替换 Sprockets

但 Rails 8 不仅仅是改进了部署和数据库适配器。我们还以 Propshaft 作为新的默认资源管道。Propshaft 是 Rails 7 中专注于 #NOBUILD 作为默认路径(并将更复杂的 JavaScript 设置卸载到 bun/esbuild/vite/etc)使命的成果。作为新的资源管道,它取代了可以追溯到 2009 年的旧 Sprockets 系统。那个时代还没有我们今天所知的 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_resetauthenticate_by。现在,借助 Rails 8,我们将所有这些组件整合到一个完整的身份验证系统生成器中,它为基于会话、可重置密码、元数据跟踪的身份验证系统提供了出色的起点。

只需运行 bin/rails generate authentication,您就会获得 SessionUser 的基本模型,以及 PasswordsMailerSessionsController 和一个 Authentication concern。您只需自行处理用户注册流程(因为这些通常是每个应用程序的定制内容)。有了这些基础,您无需担心自己构建身份验证设置(或者,天哪,为此向供应商付费!)。

以及其他所有内容

Rails 8 在 Rails 7.2 发布后仅几个月就发布了,但除了上述所有令人难以置信的新工具外,还包含大量修复和改进。Rails 目前从未如此全速前进。这是一个参与框架的绝佳时机,也是第一次加入我们这列火车的好时机。无论您是热衷于 #NOBUILD 还是 #NOPAAS,或者只是被压缩复杂性的总体使命所吸引,您都会发现自己置身于一个由充满激情的建设者组成的社区中,他们珍视优美代码与生产力同样重要。