CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Ruby on Rails 实战入门/课时/部署与运维
RawBlame
课时目录12 节

Ruby on Rails 实战入门

  1. 01Rails 概览与项目结构
  2. 02路由设计
  3. 03控制器
  4. 04Active Record 模型
  5. 05查询与优化
  6. 06数据库适配
  7. 07视图与组件
  8. 08表单
  9. 09认证与授权
  10. 10资产与后台任务
  11. 11测试与调试
  12. 12部署与运维

部署与运维

Kamal、缓存与日志。

30 分钟

部署与运维

这一课你将能做到

  1. 用 Puma + systemd 或 Kamal 把 Rails 应用推上生产服务器
  2. 配置生产环境的三件套:资产预编译、数据库迁移、密钥管理
  3. 说清楚 Rails 7/8 的 Solid 生态(Cache/Queue/Cache)如何省掉 Redis

为什么要学

能写的代码不算本事,能稳定跑在用户面前的代码才是。部署和运维是开发到上线的最后一公里,也是事故最高发的阶段:环境变量漏配、数据库迁移没跑、资产 404、连接池耗尽——任意一条都能让精心写的代码在用户面前变成白屏。Rails 8 的 Kamal 把部署简化到「一条命令上云」,中小团队终于不必深陷 Ansible/Capistrano 的泥潭。

对比本站:Spring Boot + Next.js 的部署通常拆成「Java 容器 + Nginx + Node 进程」,配置两份;Rails 全栈应用是单一进程(Puma),配好反向代理即可,部署脚本短一半。

先建立图像

用户浏览器
      │
      ▼
  Nginx / CDN(SSL、静态文件、缓存)
      │
      ▼
  Puma(Rails 进程)
      │
      ├─ Workers(2~4)× Threads(5)
      │
      ▼
  数据库(SQLite / MySQL / PostgreSQL)
      │
      ▼
  后台 Worker(Solid Queue,可选独立进程)

部署流水线:
代码推送 → CI 跑测试 → 镜像构建(Docker)→ 服务器拉镜像
  → 资产预编译 → 数据库 migrate → 切新容器 → 旧容器退役

跟着做

步骤 1:生产环境配置检查清单

config/environments/production.rb:

Rails.application.configure do
  config.cache_classes = true
  config.eager_load = true
  config.consider_all_requests_local = false   # 不暴露完整错误栈
  config.force_ssl = true                       # 强制 HTTPS
  config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
  config.active_storage.variant_processor = :mini_magick
  config.log_level = :info
  config.logger = ActiveSupport::Logger.new(STDOUT)
end

上线前必做三件事(顺序不可乱):

# 1. 预编译资产(CSS/JS 指纹化)
RAILS_ENV=production bin/rails assets:precompile

# 2. 跑数据库迁移(新增/改表)
RAILS_ENV=production bin/rails db:migrate

# 3. 重启 Puma 进程加载新代码

步骤 2:Puma 配置

config/puma.rb:

workers ENV.fetch("WEB_CONCURRENCY", 2)
threads_count = ENV.fetch("RAILS_MAX_THREADS", 5)
threads threads_count, threads_count

preload_app!

on_worker_boot do
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end
  • workers:进程数,按 CPU 核心数设(通常是核心数或核心数+1)
  • threads:每个 worker 的线程数,影响并发连接数
  • preload_app!:启动时预加载应用,节省内存(Copy-on-Write)

环境变量:

export WEB_CONCURRENCY=2       # 2 个 worker 进程
export RAILS_MAX_THREADS=5     # 每个 5 线程
export RAILS_ENV=production
export RAILS_MASTER_KEY=...    # 解密 credentials 的密钥

步骤 3:用 Kamal 一键部署(Rails 8 推荐)

Kamal 是 Rails 8 官方出的部署工具,基于 Docker,一条命令完成构建、推送、迁移、切换:

# 1. 安装并初始化
gem install kamal
kamal init

# 生成 config/deploy.yml
# servers: 你的 VPS IP
# registry: Docker Hub 或阿里云镜像仓库
# config/deploy.yml
service: blog
image: yourname/blog
servers:
  web:
    - 1.2.3.4
  job:
    hosts:
      - 1.2.3.4
    cmd: bin/jobs
registry:
  username: yourname
  password:
    - KAMAL_REGISTRY_PASSWORD
env:
  secret:
    - RAILS_MASTER_KEY
kamal setup    # 首次:装 Docker、建目录、配 traefik 反向代理
kamal deploy   # 后续:构建镜像、推仓库、迁移、切流量
kamal logs     # 看实时日志
kamal app exec "bin/rails console"  # 远程进 console

Kamal 底层用 Docker 容器运行,自带 Traefik 做反向代理和 SSL(Let's Encrypt 自动续期)。对中小项目来说,这就是「Heroku 体验的私有化替代」。

步骤 4:Solid 生态——省掉 Redis

Rails 7.1+ 推了三件套,目标是用数据库取代 Redis 担任缓存和队列:

组件角色替代对象
Solid Cache片段缓存/动作缓存Redis Cache
Solid Queue后台任务队列Sidekiq + Redis
Solid CableWebSocket(Action Cable)广播Redis Pub/Sub

启用 Solid Cache:

# config/environments/production.rb
config.cache_store = :solid_cache_store
bin/rails solid_cache:install
bin/rails db:migrate

缓存写入数据库表,天然持久化、事务一致、不需要额外运维。QPS 几千以内的内容站完全够用;超高并发才需切回 Redis。

步骤 5:监控与健康检查

控制器加一个健康检查端点:

class HealthController < ApplicationController
  skip_before_action :require_login, raise: false
  def index
    ActiveRecord::Base.connection.execute("SELECT 1")
    render plain: "OK", status: :ok
  end
end
# routes.rb
get "/up", to: "health#index"

负载均衡器 / Kamal 用它判断实例是否健康, unhealthy 时自动摘除。配合日志轮转(lograge gem 输出结构化日志)和 APM(New Relic / Sentry)形成监控闭环。

讲清楚要点

  1. 部署顺序铁律:代码→资产→迁移→重启:资产要基于最新代码编译,迁移要在服务切换前完成,重启最后。顺序错了就是白屏或数据不一致事故。
  2. 环境变量是生产配置的唯一入口:密码、密钥、第三方 token 全进 ENV,代码库零秘密。Kamal 的 env.secret 会自动注入。
  3. Puma workers × threads 的算式:总并发 = workers × threads,数据库连接池 ≥ 这个值。单机内存小就减 workers,IO 密集就加 threads。
  4. Kamal 不是唯一方案:Heroku/Fly.io 适合不想管服务器的人;Capistrano 适合老项目;Docker Swarm/K8s 适合团队已有基础设施。Kamal 是「我想自己控制服务器但不想写 500 行 Ansible」的最佳解。
  5. Solid 生态降低运维负担:一个数据库同时扛业务数据 + 缓存 + 队列,部署文档短一页。等流量真的爆了再引入 Redis,不要过度架构。

你可能会懵的地方

  • SQLite 怎么上生产? SQLite 是单文件,多 worker 共享一个文件在并发下可能锁竞争。用 solid_cache 做缓存缓解,或把 SQLite 放 fast NVMe 盘。真想高并发就上 PostgreSQL/MySQL,但不要为了「觉得生产该用 RDB」而提前引入运维成本。

  • assets:precompile 为什么慢? 首次编译所有 JS/CSS 指纹。开发时不需要,只有 CI/CD 或生产部署跑。加 RAILS_ENV=production 时跳过 jsbundling 可提速(纯 Importmap 项目已很快)。

  • Kamal 和 Docker Compose 区别? Docker Compose 适合本地/单机编排;Kamal 是专为 Web 部署设计的 CLI,封装了镜像构建、多机分发、零停机切换(blue/green 部署)、SSL 终止、日志聚集。

  • 零停机部署怎么做到的? Kamal 先启动新容器跑健康检查,通过后切流量,再停旧容器。期间请求由 Traefik 平滑转发,用户无感知。这叫 rolling update。

  • 日志打到哪里? Docker 容器日志输出到 STDOUT,Kamal 用 kamal logs 聚合。生产配 lograge gem 输出 JSON,对接日志平台(ELK / Datadog)。

错法对照

错法问题正解
生产 eager_load = false第一次请求时才加载,慢且易超时production.rb 必须 eager_load = true
部署顺序:重启→迁移新代码跑在老结构上,报错先迁移,再重启
master.key 提交到仓库生产密钥泄露加入 .gitignore,服务器 ENV 注入
把 secrets 写死在代码里改密码要发版全走环境变量或 credentials
没有健康检查端点实例挂了负载均衡不知道/up 检查 DB 连通性

卡点急救

  1. 上线后静态文件 404:生产环境 public_file_server 未启用且 Nginx 没配 assets 目录;或预编译没跑。检查 public/assets/ 下有无带指纹文件,Nginx alias 是否指向正确。
  2. ActiveRecord::ConnectionTimeoutError:连接池 < 总线程数。检查 pool(database.yml)和 RAILS_MAX_THREADS(Puma 配置),确保 pool ≥ threads,还要加 Sidekiq 的并发余量。
  3. Kamal 部署后服务起不来:SSH 进服务器 kamal app logs 看报错;常见是数据库没建、迁移未跑、master key 不对。Kamal 的 app exec "bin/rails db:migrate" 可远程执行补救。

面试常问

  • Rails 生产环境部署的核心步骤和顺序? 答:①代码拉取/镜像构建 → ②资产预编译 → ③数据库迁移 → ④零停机切换容器/进程 → ⑤旧实例退役。顺序不能乱:迁移必须在服务切换前完成,否则新代码读老结构;资产必须在重启前编译,否则指纹对不上。

  • Puma workers 和 threads 怎么配? 答:workers 对应进程数,CPU 核心数或稍多(内存允许下);threads 对应单进程内的并发数,IO 密集型可设 10~16,计算密集型 5 左右。总并发 = workers × threads,数据库连接池 ≥ 该值。内存不够时优先减 workers(线程共享进程内存)。

  • Kamal 解决了什么问题? 答:把 Rails 部署从「写几百行 Ansible/Capistrano 脚本 + 配 Nginx + 手动 SSL + 各自为政的日志」压缩成一条 kamal deploy 命令。基于 Docker 保证环境一致,自带 Traefik 做反向代理和自动证书,默认零停机切换。是 Rails 8 对「部署体验」的官方回答。

自测三问

  1. assets:precompile 和 db:migrate 为什么必须在服务重启前执行?顺序错了会发生什么?
  2. Solid Cache 相比 Redis 省掉了什么?在什么量级下可能成为瓶颈?
  3. Kamal 的零停机切换大概是怎么实现的?旧容器什么时候停止?

小结一句话

部署纪律:资产先编译、迁移再切流量、密钥走环境变量、监控接健康检查——Kamal 一条命令把 Rails 推上线。

延伸

  • Kamal 官方文档
  • Solid Cache 与 Solid Queue 指南
  • 本 track 全部 12 课至此结束,建议回到 Ruby on Rails 路线图 逐节点标记掌握程度。
加载本节练习…
← 上一课测试与调试