
生产环境部署 VanityUnicorn/Passenger 下数据库连接管理避坑指南【免费下载链接】vanityExperiment Driven Development for Ruby项目地址: https://gitcode.com/gh_mirrors/va/vanityVanity 是一个面向 Rails 的 A/B 测试框架Experiment Driven Development支持 Redis、MongoDB、ActiveRecord 等多种数据源通过experiments/目录下的 Ruby 文件定义实验开箱即用。然而把 Vanity 部署到生产环境时一个极其隐蔽的坑会悄悄出现在 Unicorn、Passenger 这类 fork 型 Web 服务器下Vanity 的数据库连接如果不做管理就会出现连接失效、数据写错、实验数据丢失等问题。本文围绕生产环境部署 Vanity 的连接管理给出完整避坑方案。一、先搞懂问题为什么 fork 之后 Vanity 连接会失效Unicorn 与 Passenger尤其是 smart spawning 模式都是先启动 master 进程再 fork 出多个 worker的模型。fork 出来的子进程会继承父进程的文件描述符包括已经建立的 Redis TCP 连接、ActiveRecord 连接池等。问题出在这里风险点后果master 的连接被多个 worker 共享同一 socket 被并发读写数据互相污染部分连接在 fork 后处于异常状态直接使用报错甚至进程崩溃连接未隔离实验参与者分组、转化数据错乱所以生产环境部署 Vanity 的第一原则是每个 worker 进程都要建立自己独立的数据库连接。二、Vanity 连接管理核心 APIconnect! / disconnect! / reconnect!Vanity 提供三个核心方法定义在lib/vanity/vanity.rbVanity.connect!建立连接参数可来自config/vanity.yml也可显式传入Vanity.disconnect!关闭当前连接Vanity.reconnect!先断开再重连等价于 disconnect! connect!连接对象由lib/vanity/connection.rb的Vanity::Connection管理会根据配置自动选择 Redis、MongoDB 或 ActiveRecord 适配器各适配器实现见lib/vanity/adapters/。三、Unicorn 部署 Vanity 的正确配置after_fork 里重连在config/unicorn.rb中加入after_fork do |server, worker| defined?(Vanity) Vanity.reconnect! end两个关键点每个 worker fork 完成后都会重新建立连接互不干扰用defined?(Vanity)做防御性判断避免在 Vanity 尚未加载的进程中报错四、Passenger 部署 Vanity自动重连机制与手动兜底好消息是Vanity 在lib/vanity/frameworks/rails.rb中已经内置了 Passenger 的重连逻辑通过PhusionPassenger.on_event(:starting_worker_process)监听 worker 启动事件fork 后自动调用Vanity.playground.reconnect!。不过为了稳妥官方仍建议在 initializer 中手动兜底if defined?(PhusionPassenger) PhusionPassenger.on_event(:starting_worker_process) do |forked| # 仅在 smart spawning 模式fork 场景下重连 if forked defined?(Vanity) Vanity.reconnect! end end end注意forked参数Passenger 在非 fork 场景下不需要重连只处理forked true的情况即可。五、显式连接参数时的顺序坑先 disconnect 再 connect如果你使用显式参数建立连接例如复用已有的 Redis 连接Vanity.connect!( adapter: :redis, redis: $redis )那么在 fork 后的重连流程中必须先断开旧连接再建立新连接Vanity.disconnect! Vanity.connect!( adapter: :redis, redis: $redis )否则来自 master 的旧 socket 会残留导致连接泄漏和状态错乱。Vanity.reconnect!内部正是按这个顺序执行的这也是它被推荐用于 fork 场景的原因。六、生产环境数据源配置config/vanity.yml连接参数默认从config/vanity.yml读取读取逻辑在lib/vanity/configuration.rb按环境区分。Redis 生产配置示例production: adapter: redis url: redis://% ENV[REDIS_USER] %:% ENV[REDIS_PASSWORD] %% ENV[REDIS_HOST] %:% ENV[REDIS_PORT] %/0使用 ActiveRecord 作为数据源时production: adapter: active_record active_record_adapter: postgresql % uri URI.parse(ENV[DATABASE_URL]) % host: % uri.host % username: % uri.user % password: % uri.password % port: % uri.port % database: % uri.path.sub(/, ) %建议把敏感信息全部用环境变量注入避免密钥写进版本库。七、更多生产环境避坑要点rake 任务自动跳过连接lib/vanity/autoconnect.rb内置了一份任务黑名单db:migrate、assets:precompile等任务不会触发连接建立避免部署流程中无谓报错数据源故障优雅降级开启config.failover_on_datastore_error true当 Redis 等数据源异常时Vanity 会调用on_datastore_error回调记录日志而不是直接抛异常保证主业务不受影响VANITY_DISABLED 环境变量临时停用 Vanity如维护窗口时设置该变量即可连接不会建立Redis 连接建议复用lib/vanity/adapters/redis_adapter.rb中会自动设置thread_safe: true并支持传入已有的 Redis 实例redis: $redis与你的连接池统一管理八、如何验证生产部署是否正常部署完成后建议按以下顺序检查✅ 打开/vanity报告页面确认实验与指标数据正常显示✅ 观察 worker 日志确认没有连接相关报错✅ 用vanity report --output vanity.html生成本地报告抽查参与人数与转化数是否符合预期✅ 重启 worker 后再次访问确认重连机制生效这是 fork 场景最容易出问题的地方搞定以上几点Vanity 在 Unicorn / Passenger 下的生产环境部署就基本不会踩连接管理的坑了。【免费下载链接】vanityExperiment Driven Development for Ruby项目地址: https://gitcode.com/gh_mirrors/va/vanity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考