部署 使用 Capistrano 部署,时间超长,原因是什么?

sefier · 2020年06月28日 · 最后由 SpiderEvgn 回复于 2020年07月16日 · 2576 次阅读

最近一年没用 rails,最近一个小项目,上了 rails,把环境搭建了一遍,采用 Rails 6.0 + Mysql 8.0 + Ruby 2.6.3,部署上线。发现 Capistrano 部署极慢,哪怕没做任何资源文件的修改,也要很长时间。卡在了 deploy:assets:precompile 上面,这是什么原因,如何避免?

比如下面这个,居然耗时接近 500S

输出信息里有写,你的 application.js 文件超出了推荐大小

建议先检查一下里面用了什么第三方库,会占用这么大文件。

brookepowell 回复

这应该只是一个提醒吧,我本地执行这个命令很快。部署这么慢,不应该是这个问题。

sefier 回复

编译前端资源很消耗 CPU 的,我记得有 Cap 的 recipe 在本地编译传到服务器的

前端编译是大坑,之前用 gitlab ci 跑 yarn build,cpu 马上上 100 多

第一次是慢的,但是第二次就快了。也可以吧node_modules,tmp/cachepublic/packs加到 linked_dirs。

经过一天的时间,这个问题解决了。本着有问有答的精神,我总结一下:

1)关于原因:应该就是服务器的 CPU 性能原因,买的是阿里云的突发性能实例,因为这个项目只有我们内部偶尔用,本着节约成本的精神买的高度共享实例。

2)解决方案:诚如@imadbc 所言,我是用这个插件解决的,我一开始也注意到了这个插件,之所以没考虑,是因为已经一年多没人维护了,大概率是不良项目,没想到还能用。

3)这个方案有个问题,服务器是 rbenv,本地是 rvm 的情况下,会在本地执行 rbenv 命令,而本地没有,故而报错。为了解决这个问题,我本地将 rvm 迁移到 rbenv,顺便我把 brew 重装了一下,就这两个事情折腾了我一天,遇到了各种奇葩问题,有五六个小时不停的 google 和 stackoverflow,真是什么问题都遇到了。虽然 rbenv 理念更先进,不知道是不是我打开方式不对,居然一直跳坑,主要原因可能跟 homebrew 的重装有关系。总之,花了一天时间都是踩这些坑。

4)如果有同学想用这个方案的话,文档里写移除require 'capistrano/rails/assets',你的文件里可能没有这一行,是因为你用了capistrano/rails,那么删掉这一行,改成 require 'capistrano/bundler' require 'capistrano/rails/migrations'

5)效果测试:没有修改 js 文件,修改其他文件,耗时 17 秒;如果修改了 js 文件,耗时 24 秒。表现良好,完全解决了这个问题。

跑题一下,是时候改用 Docker 部署了。

发布前通过 GitLab CI 打包好 Docker Image,发布 / 回滚 / 服务器水平扩展将会变得更容易。

huacnlee 回复

目前使用 docker-compose 的时候出现一个问题

在升级 image 完毕后, 重新运行 docker-compose 的时候 这个时候新的 docker image 有启动时间 这段时间会 502

大概几秒, docker 里的 puma 启动完毕后就没这个现象了

huacnlee 回复

研究了一段时间,因为是小项目,对 Docker 不熟悉,所以放弃了。我离开 Rails 社区有段时间了,倒是有兴趣在大型项目这么操作,但是网上资料少得可怜,有没有什么推荐的 Rails 部署方面的 Docker/K8S 资料推荐一下?我之前用 capistrano 部署过 300 台服务器,实在很痛苦。

jicheng1014 回复

compose 是用于本地开发而不是用于部署的。部署要用 swarm,配置是延续 compose 的配置。

puma/unicorn 热重启是通过管理进程,在重启过程保持接口的监听,在重启结束后移交接口。swarm 也实现了这样的重启,swarm 本身接管网络,滚动重启容器,维持访问把流量转到可用的容器上。

Rei 回复

ps 是使用的 swarm 的

类似这样的配置么

deploy:
  replicas: 3
  update_config:
    parallelism: 1
    delay: 5s

另外还有个地方还想请教下

就是 docker 下 静态文件夹 public 的管理.

因为配置等原因, 我们还是期望 nginx 不在容器中运行 puma 提供的服务, 本身我们可以依赖 upstream, 但是静态文件这块就有点尴尬,

之前我们的做法是 有个 container 专门接受从外层主机挂载的目录 /tmp/public, 之后这个镜像 run 的指令就是 cp -r public /tmp/public

这样外层的机器就获得了镜像里的 public 文件夹, 但是我觉得这种方式属于取巧的邪道

能否参考下您的解决方案 或者 有人能好心分享下么?

jicheng1014 回复

静态文件用 CDN 处理。Web server 提供静态文件,CDN 回源的时候缓存。

谢谢楼主。

jicheng1014 回复

我跟你一样。。。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册