应用维护与多版本 Ruby 部署实战
在应用的生命周期中,维护和版本管理是至关重要的环节。无论是处理应用的停机时间,还是在同一服务器上运行多个不同版本的 Ruby 应用,都需要精心的规划和有效的策略。下面将详细介绍如何优化应用的停机时间,以及如何使用 Ruby 环境管理器(RVM)在服务器上部署多个不同版本的 Ruby 应用。
1. 优化应用停机时间
即使我们竭尽全力让应用 24/7 运行,也难免会遇到应用不可用的情况。停机时间可分为计划内停机和计划外停机。
-
计划内停机
:在现实世界中,由于各种原因,如数据中心迁移、核心服务或硬件升级、耗时的数据库迁移等,我们可能需要安排应用停机。为了将对用户的干扰降到最低,我们需要进行充分的规划和沟通。
- 选择停机窗口 :一般选择用户使用量最少的时间段进行停机。通过收集的指标数据,找到合适的时间点,并将停机窗口设置为以该时间点为中心。如果停机窗口在半夜,建议设置两个闹钟,提前一小时起床,确保在停机开始时保持清醒。同时,至少安排两人在线,保持电话畅通,以便相互协作,避免在清晨做出错误的决策。此外,将停机窗口设置得比预期长一小时,这样如果能提前完成,会带来额外的惊喜。
- 编写脚本并进行测试 :详细列出停机期间的每一个步骤,并在非生产环境中进行测试。非生产环境可以是在笔记本电脑上运行的几个 Vagrant VM,越接近生产环境越好。例如,由于长时间的数据库架构更改导致的停机脚本可能如下:
1. Shut down the cron daemon on all servers (sudo /sbin/service crond stop).
2. Shut down the background workers (sudo /sbin/service workers stop).
3. Deploy the new code with the database change (cap production deploy).
4. In an after_deploy hook, publish the maintenance page *MassiveApp is now offline*.
5. Run the database schema change (RAILS_ENV=production rake db:migrate).
6. Check for schema change success by examining the output of SHOW CREATE TABLE accounts.
7. Remove the maintenance page *MassiveApp is now back online*.
8. Restart the cron daemon on all servers (sudo /sbin/service crond start).
9. Restart the background workers (sudo /sbin/service workers start).
- **沟通停机信息**:通过在 status.massiveapp.com 上发布消息、向登录用户显示即将停机的提示信息,以及在停机前几小时在 massiveapp.com 上发布横幅等方式,将停机信息告知用户。同时,准备一个温馨的维护页面,向用户强调应用正在进行改进,重新上线后将提供更好的性能和更多的功能。
-
计划外停机
:计划外停机无法提前沟通,也没有预先编写的恢复脚本,而且通常发生在对用户最不方便的时间。为了减少计划外停机的影响,我们可以提前采取以下措施:
- 制定升级计划 :当应用意外离线时,监控系统应及时通知相关人员。该人员应能够访问一份电话号码列表,以便联系关键开发人员。如果团队人员充足,可以轮流值班,确保有人能够在需要时及时响应。
- 尽快恢复服务 :一旦相关人员到位,应尽快让应用重新上线。同时,可以在应用恢复后再深入分析问题的原因。在这个过程中,多人参加电话会议非常有用,有人可以在会议中说“给我三十秒复制这些日志”,从而捕获定位停机问题所需的数据。
- 与用户沟通 :在状态页面上发布“网站已关闭…我们正在处理”的消息,让用户知道你已经意识到问题。对于长时间的停机(超过五分钟),建议每十五分钟更新一次状态页面。除非确定能够在五分钟内恢复,否则不要轻易承诺“我们将在五分钟内恢复”。例如,发布“正在从备份中恢复…已完成 75%”的消息可以让用户知道你正在取得进展。
- 保持冷静和专业 :与计划内停机一样,保持冷静、诚实和专业非常重要。没有人希望停机发生,每个人都希望网站尽快恢复并了解原因,因此应专注于这些共同目标。如果你最近进行了更改,即使认为“不可能导致问题”,也应该坦诚承认,因为其他人可能会根据你提供的数据找到问题的根源。让停机的紧急情况成为凝聚团队的契机。
2. 使用 RVM 管理多版本 Ruby
在某些情况下,我们可能需要在同一服务器上运行多个不同版本的 Ruby 应用。Ruby 环境管理器(RVM)可以帮助我们轻松实现这一目标。
-
安装 RVM
- 启动新的虚拟机 :使用 plain lucid64 基础盒子启动一个新的虚拟机。
$ mkdir ~/deployingrails/vagrant_rvm && cd ~/deployingrails/vagrant_rvm/
$ vagrant init lucid64
$ vagrant up
- **更新系统并安装依赖库**:确保使用最新的软件包列表,安装一些开发库,并移除默认的 Ruby 版本。
$ vagrant ssh
vm $ sudo apt-get update -y
vm $ sudo apt-get install build-essential zlib1g-dev libssl-dev libreadline-dev \
git-core curl libyaml-dev libcurl4-dev libsqlite3-dev -y
vm $ sudo rm -rf /opt/vagrant_ruby
- **安装 RVM**:使用快捷方法安装最新的稳定版本。
vm $ curl -L get.rvm.io | bash -s stable
- **启用 RVM**:通过重新加载 shell 环境来启用 RVM。
vm $ source .profile
- **验证 RVM 安装**:使用 -h 标志验证 RVM 是否安装成功,并查看详细的使用说明。
vm $ rvm -h
- **安装不同版本的 Ruby**:安装 Ruby 1.9.3 和 Ruby 1.8.7。
vm $ rvm install 1.9.3
vm $ rvm install 1.8.7
- **查看已安装的 Ruby 版本**:使用 rvm list 命令查看 RVM 管理的 Ruby 版本。
vm $ rvm list
- **切换 Ruby 版本**:使用 rvm use 命令在不同版本的 Ruby 之间切换。
vm $ rvm use 1.9.3
vm $ ruby -v
vm $ rvm use 1.8.7
vm $ ruby -v
- **配置 .rvmrc 文件**:RVM 使用 .rvmrc 文件来确定应加载哪个 Ruby 解释器。为了简化管理,我们可以假设所有的 .rvmrc 文件都是可信的,并在 vagrant 用户的 $HOME/.rvmrc 文件中设置相应的选项,然后重新加载 RVM 的配置。
vm $ echo 'export rvm_trust_rvmrcs_flag=1' >> $HOME/.rvmrc
vm $ rvm reload
- **创建应用目录并配置 .rvmrc 文件**:分别创建用于存放 Ruby 1.9.3 和 Ruby 1.8.7 应用的目录,并在相应的目录中创建和加载 .rvmrc 文件。
vm $ mkdir app193
vm $ echo "rvm use 1.9.3" > app193/.rvmrc
vm $ cd app193/
vm $ cd ~/
vm $ mkdir app187
vm $ echo "rvm use 1.8.7" > app187/.rvmrc
vm $ cd app187/
通过以上步骤,我们可以优化应用的停机时间,确保在必要时能够顺利进行维护和升级。同时,使用 RVM 可以方便地管理多个不同版本的 Ruby 应用,满足不同项目的需求。在实际应用中,我们还可以根据具体情况进行进一步的优化和调整,以提高应用的稳定性和性能。
应用维护与多版本 Ruby 部署实战
3. 使用 Passenger Standalone 服务多版本 Ruby 应用
在前面的配置中,我们通常会让 Passenger 运行的所有应用使用相同的 Ruby 版本。但这次我们要运行两个不同 Ruby 版本的应用,由于不能在
httpd.conf
文件中设置两个
PassengerRuby
指令,所以我们将使用 Passenger Standalone。
-
架构原理 :Passenger Standalone 运行自己的 Web 服务器(一个 nginx 实例)。这个 nginx 实例监听一个端口,并将请求代理到指定的 Rails 应用。它既可以监听外部端口并独立提供应用服务,也可以设置在前端 Web 服务器后面,由前端服务器将请求代理回 Passenger Standalone。
-
端口转发配置 :
-
退出虚拟机,编辑
Vagrantfile,配置端口 4000 和 4001 的转发。
-
退出虚拟机,编辑
Vagrant::Config.run do |config|
config.vm.box = "lucid64"
config.vm.forward_port 3000, 4000
config.vm.forward_port 3001, 4001
end
2. 重新加载虚拟机以启用端口转发。
vm $ exit
$ vagrant reload
-
设置 Ruby 1.9.3 应用
:
-
重新连接到虚拟机,进入
app193目录。
-
重新连接到虚拟机,进入
$ vagrant ssh
vm $ cd app193/
2. 安装 Rails 和 Passenger 相关依赖。
vm $ gem install rails -v=3.2.1 --no-rdoc --no-ri
vm $ rails new .
vm $ echo "gem 'therubyracer'" >> Gemfile
vm $ bundle
vm $ rails generate scaffold post content:string && rake db:migrate
vm $ gem install passenger -v=3.0.11 --no-rdoc --no-ri
3. 启动 Passenger Standalone 并在后台运行。
vm $ passenger start --daemonize
启动后,在浏览器中访问 `http://localhost:4000/posts/` 即可看到测试应用。默认的 Rails 环境是开发环境,我们也可以使用 Passenger 的 `--environment` 标志在生产模式下启动应用。
-
设置 Ruby 1.8.7 应用
:
-
进入
app187目录。
-
进入
vm $ cd ~/app187/
2. 安装 Rails 和 Passenger 相关依赖。
vm $ gem install rails -v=3.2.1 --no-rdoc --no-ri
vm $ rails new .
vm $ echo "gem 'therubyracer'" >> Gemfile
vm $ bundle
vm $ rails generate scaffold game name:string && rake db:migrate
vm $ gem install passenger -v=3.0.11 --no-rdoc --no-ri
3. 启动 Passenger Standalone 并指定端口 3001 在后台运行。
vm $ passenger start --port 3001 --daemonize
以下是一个简单的流程图,展示了使用 Passenger Standalone 部署多版本 Ruby 应用的步骤:
graph LR
A[启动虚拟机] --> B[配置端口转发]
B --> C[设置 Ruby 1.9.3 应用]
B --> D[设置 Ruby 1.8.7 应用]
C --> C1[安装依赖]
C1 --> C2[启动 Passenger Standalone]
D --> D1[安装依赖]
D1 --> D2[启动 Passenger Standalone]
4. 总结
通过上述的操作,我们掌握了优化应用停机时间的方法,包括计划内停机和计划外停机的处理策略。同时,学会了使用 RVM 管理多个不同版本的 Ruby 应用,并使用 Passenger Standalone 为这些应用提供服务。
下面是一个总结表格,对比计划内停机和计划外停机的处理要点:
| 停机类型 | 处理要点 |
| ---- | ---- |
| 计划内停机 | 选择合适停机窗口、编写并测试脚本、与用户充分沟通 |
| 计划外停机 | 制定升级计划、尽快恢复服务、及时与用户沟通、保持冷静专业 |
在实际的应用维护和部署过程中,我们可以根据具体的业务需求和技术架构,灵活运用这些方法和工具,不断优化应用的性能和稳定性,为用户提供更好的服务体验。同时,持续关注技术的发展和变化,不断学习和掌握新的技术和方法,以应对不断变化的应用场景和挑战。
超级会员免费看
1806

被折叠的 条评论
为什么被折叠?



