记录一下使用如下工具搭建一个简单的Ruby Web应用的过程:

工具集:

  • Nginx — 前端服务器
  • Unicorn — 应用容器
  • Capistrano — 自动部署工具
  • Sinatra — 极轻量级Web框架

步骤:

  1. 使用Sinatra提供的DSL编写一个能够运行的最小化web应用:

    # Gemfile
    source 'http://ruby.taobao.org/'
    gem 'sinatra'
    

    # app.rb
    require 'sinatra'get '/' do'Hello world'
    end
    

    使用bundle exec ruby app.rb检验应用是否能正常运行:

    twer@app$ bundle exec ruby app.rb
    [2014-02-06 03:06:59] INFO  WEBrick 1.3.1
    [2014-02-06 03:06:59] INFO  ruby 1.9.3 (2013-11-22) [x86_64-darwin13.0.0]
    == Sinatra/1.4.4 has taken the stage on 4567 for development with backup from WEBrick
    [2014-02-06 03:06:59] INFO  WEBrick::HTTPServer#start: pid=62687 port=4567
    

    访问http://localhost:4567应该能得到’Hello world’的响应

  2. 现在将其整理为Rack-based app:

    # app.rb
    require 'sinatra'class App < Sinatra::Baseget '/' do'Hello world'end
    end
    

    # config.ru
    root = ::File.dirname(__FILE__)
    require ::File.join(root, 'app')run App
    

    使用rackup -p1818检验应用是否能正常运行:

    twer@app$ rackup -p1818
    Thin web server (v1.6.1 codename Death Proof)
    Maximum connections set to 1024
    Listening on 0.0.0.0:1818, CTRL+C to stop
    

    访问http://localhost:1818应该能得到’Hello world’的响应

  3. 引入unicorn和capistrano配置:

    # Gemfile
    source 'http://ruby.taobao.org/'
    gem 'sinatra'
    gem 'unicorn'
    gem 'capistrano', '~> 2.15.5'
    gem 'rvm-capistrano'
    

    使用bundle install安装相应的gem包后,运行capify .生成部署所需的配置文件:

    twer@app$ capify .
    [add] writing './Capfile'
    [add] making directory './config'
    [add] writing './config/deploy.rb'
    [done] capified!
    

    配置config/deploy.rb,注意git仓库地址的配置,以及阿里云服务器ip地址及用户名的配置:

    # config/deploy.rb
    require 'rvm/capistrano'
    set :rvm_ruby_string, '1.9.3'
    set :rvm_type, :system# Bundler tasks
    require 'bundler/capistrano'# Your application name
    set :application, 'my-ruby-web-demo'# Input your git repository address
    set :repository,  'git@github.com:tongzh/my-ruby-web-demo.git'set :scm, :git# do not use sudo
    set :use_sudo, false
    set(:run_method) { use_sudo ? :sudo : :run }# This is needed to correctly handle sudo password prompt
    default_run_options[:pty] = true# Input your username to login remote server address
    set :user, 'root'
    set :group, user
    set :runner, user# Input your server address
    set :host, "#{user}@115.28.137.21"
    role :web, host
    role :app, hostset :rails_env, :production# Where will it be located on a server?
    set :deploy_to, "/srv/#{application}"
    set :unicorn_conf, "#{deploy_to}/current/config/unicorn.rb"
    set :unicorn_pid, "#{deploy_to}/shared/pids/unicorn.pid"# Unicorn control tasks
    namespace :deploy dotask :restart dorun "if [ -f #{unicorn_pid} ]; then kill -USR2 `cat #{unicorn_pid}`; else cd #{deploy_to}/current && bundle exec unicorn -c #{unicorn_conf} -E #{rails_env} -D; fi"endtask :start dorun "cd #{deploy_to}/current && bundle exec unicorn -c #{unicorn_conf} -E #{rails_env} -D"endtask :stop dorun "if [ -f #{unicorn_pid} ]; then kill -QUIT `cat #{unicorn_pid}`; fi"end
    end
    

    新建config/unicorn.rb文件,对unicorn进行配置:

    # config/unicorn.rb
    deploy_to = '/srv/my-ruby-web-demo'
    rails_root = "#{deploy_to}/current"
    pid_file = "#{deploy_to}/shared/pids/unicorn.pid"
    socket_file= "#{deploy_to}/shared/unicorn.sock"
    log_file = "#{rails_root}/log/unicorn.log"
    err_log = "#{rails_root}/log/unicorn_error.log"
    old_pid = pid_file + '.oldbin'timeout 30
    worker_processes 2 # increase or decrease
    listen socket_file, :backlog => 1024pid pid_file
    stderr_path err_log
    stdout_path log_file# make forks faster
    preload_app true# make sure that Bundler finds the Gemfile
    before_exec do |server|ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
    endbefore_fork do |server, worker|defined?(ActiveRecord::Base) andActiveRecord::Base.connection.disconnect!# zero downtime deploy magic:# if unicorn is already running, ask it to start a new process and quit.if File.exists?(old_pid) && server.pid != old_pidbeginProcess.kill("QUIT", File.read(old_pid).to_i)rescue Errno::ENOENT, Errno::ESRCH# someone else did our job for usendend
    endafter_fork do |server, worker|# re-establish activerecord connections.defined?(ActiveRecord::Base) andActiveRecord::Base.establish_connection
    end
    

    然后push代码到git仓库。

  4. 在正式进行部署前,ssh登录到远程主机上依次安装所需的软件环境:
    • 安装RVM和Ruby
    • 安装git
    • 添加github ssh key
  5. 依次使用cap deploy:setupcap deploy命令进行部署:

    twer@app<master>$ cap deploy:setuptriggering load callbacks* 2014-02-06 21:13:12 executing `deploy:setup'* executing "mkdir -p /srv/my-ruby-web-demo /srv/my-ruby-web-demo/releases /srv/my-ruby-web-demo/shared /srv/my-ruby-web-demo/shared/system /srv/my-ruby-web-demo/shared/log /srv/my-ruby-web-demo/shared/pids"servers: ["115.28.137.21"]
    Password: [root@115.28.137.21] executing commandcommand finished in 647ms* executing "chmod g+w /srv/my-ruby-web-demo /srv/my-ruby-web-demo/releases /srv/my-ruby-web-demo/shared /srv/my-ruby-web-demo/shared/system /srv/my-ruby-web-demo/shared/log /srv/my-ruby-web-demo/shared/pids"servers: ["115.28.137.21"][root@115.28.137.21] executing commandcommand finished in 644ms
    

    twer@app<master>$ cap deploytriggering load callbacks* 2014-02-06 21:20:06 executing `deploy'* 2014-02-06 21:20:06 executing `deploy:update'** transaction: start* 2014-02-06 21:20:06 executing `deploy:update_code'executing locally: "git ls-remote git@github.com:tongzh/my-ruby-web-demo.git HEAD"command finished in 7722ms* executing "git clone -q git@github.com:tongzh/my-ruby-web-demo.git /srv/my-ruby-web-demo/releases/20140206102014 && cd /srv/my-ruby-web-demo/releases/20140206102014 && git checkout -q -b deploy 0de5794f2d7e13af76e671df6a7796c676e88e2b && (echo 0de5794f2d7e13af76e671df6a7796c676e88e2b > /srv/my-ruby-web-demo/releases/20140206102014/REVISION)"servers: ["115.28.137.21"]
    Password: [root@115.28.137.21] executing commandcommand finished in 4891ms* 2014-02-06 21:20:25 executing `deploy:finalize_update'triggering before callbacks for `deploy:finalize_update'* 2014-02-06 21:20:25 executing `bundle:install'* executing "cd /srv/my-ruby-web-demo/releases/20140206102014 && bundle install --gemfile /srv/my-ruby-web-demo/releases/20140206102014/Gemfile --path /srv/my-ruby-web-demo/shared/bundle --deployment --quiet --without development test"servers: ["115.28.137.21"][root@115.28.137.21] executing commandcommand finished in 45056ms* executing "chmod -R -- g+w /srv/my-ruby-web-demo/releases/20140206102014 && rm -rf -- /srv/my-ruby-web-demo/releases/20140206102014/public/system && mkdir -p -- /srv/my-ruby-web-demo/releases/20140206102014/public/ && ln -s -- /srv/my-ruby-web-demo/shared/system /srv/my-ruby-web-demo/releases/20140206102014/public/system && rm -rf -- /srv/my-ruby-web-demo/releases/20140206102014/log && ln -s -- /srv/my-ruby-web-demo/shared/log /srv/my-ruby-web-demo/releases/20140206102014/log && rm -rf -- /srv/my-ruby-web-demo/releases/20140206102014/tmp/pids && mkdir -p -- /srv/my-ruby-web-demo/releases/20140206102014/tmp/ && ln -s -- /srv/my-ruby-web-demo/shared/pids /srv/my-ruby-web-demo/releases/20140206102014/tmp/pids"servers: ["115.28.137.21"][root@115.28.137.21] executing commandcommand finished in 692ms* executing "find /srv/my-ruby-web-demo/releases/20140206102014/public/images /srv/my-ruby-web-demo/releases/20140206102014/public/stylesheets /srv/my-ruby-web-demo/releases/20140206102014/public/javascripts -exec touch -t 201402061021.11 -- {} ';'; true"servers: ["115.28.137.21"][root@115.28.137.21] executing command** [out :: root@115.28.137.21] find: `/srv/my-ruby-web-demo/releases/20140206102014/public/images': No such file or directory** [out :: root@115.28.137.21] find: `/srv/my-ruby-web-demo/releases/20140206102014/public/stylesheets': No such file or directory** [out :: root@115.28.137.21] find: `/srv/my-ruby-web-demo/releases/20140206102014/public/javascripts': No such file or directorycommand finished in 655ms* 2014-02-06 21:21:12 executing `deploy:create_symlink'* executing "rm -f /srv/my-ruby-web-demo/current &&  ln -s /srv/my-ruby-web-demo/releases/20140206102014 /srv/my-ruby-web-demo/current"servers: ["115.28.137.21"][root@115.28.137.21] executing commandcommand finished in 702ms** transaction: commit* 2014-02-06 21:21:12 executing `deploy:restart'* executing "if [ -f /srv/my-ruby-web-demo/shared/pids/unicorn.pid ]; then kill -USR2 `cat /srv/my-ruby-web-demo/shared/pids/unicorn.pid`; else cd /srv/my-ruby-web-demo/current && bundle exec unicorn -c /srv/my-ruby-web-demo/current/config/unicorn.rb -E production -D; fi"servers: ["115.28.137.21"][root@115.28.137.21] executing commandcommand finished in 1633ms
    

    确保以上操作无异常输出,然后登录到远程主机上查看应用是否已正常装载到unicorn进程中:

    root@~$ ps aux | grep my-ruby-web-demo
    root     20071  0.0  7.3 218396 37016 ?        Sl   21:21   0:00 unicorn master -c /srv/my-ruby-web-demo/current/config/unicorn.rb -E production -D
    root     20074  0.0  7.2 218396 36476 ?        Sl   21:21   0:00 unicorn worker[0] -c /srv/my-ruby-web-demo/current/config/unicorn.rb -E production -D
    root     20076  0.0  7.2 218396 36476 ?        Sl   21:21   0:00 unicorn worker[1] -c /srv/my-ruby-web-demo/current/config/unicorn.rb -E production -D
    root     20141  0.0  0.1 103208   824 pts/1    S+   21:23   0:00 grep my-ruby-web-demo
    
  6. 在远程主机上安装nginx,并在nginx配置中增添一个反向代理配置,将请求分发给应用所在的unicorn进程:

    # /etc/nginx/default.conf
    upstream my-ruby-web-demo-unicorn {server unix:/srv/my-ruby-web-demo/shared/unicorn.sock fail_timeout=0;
    }server {listen       80;server_name  localhost;root /srv/my-ruby-web-demo/current/public;location / {try_files $uri @net;}location @net {proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $http_host;proxy_redirect off;proxy_pass http://my-ruby-web-demo-unicorn;}error_page  404              /404.html;# redirect server error pages to the static page /50x.htmlerror_page   500 502 503 504  /50x.html;location = /50x.html {root   /usr/share/nginx/html;}
    }
    

    在远程主机上重启nginx:service nginx restart,之后通过远程主机的ip就可以访问到所部署的应用程序的’Hello world’响应了。

参考:

  • Deploying With Sinatra + Capistrano + Unicorn
  • Capistrano + Nginx + Unicorn + Sinatra on Ubuntu

使用Nginx+Unicorn+Capistrano+Sinatra搭建Ruby Web应用相关推荐

  1. nginx和squid配合搭建的web服务器前端系统

    两种前端架构: lvs -> nginx前端代理 -> squid缓存 lvs -> squid前端缓存 -> nginx中层代理 squid在前面的优点: Squid作纯代理 ...

  2. Centos 搭建高性能WEB服务 Nginx+PHP+MYSQL+Discuz论坛

    Centos 搭建高性能WEB服务 Nginx+PHP+MYSQL+Discuz论坛 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运 ...

  3. Nginx + FastCGI 程序(C/C++) 搭建高性能web service的Demo及部署发布

    1.介绍     Nginx - 高性能web server,这个不用多说了,大家都知道.     FastCGI程序 - 常驻型CGI程序,它是语言无关的.可伸缩架构的CGI开放扩展,其主要行为是将 ...

  4. python django mysql安装_Django+Nginx+uWSGI+Mysql搭建Python Web服务器

    原标题:Django+Nginx+uWSGI+Mysql搭建Python Web服务器 安装的时候全部选择英文,记得以前选择中文的时候安装时出了问题,服务器组件一个不选,Ubuntu安装做的很贴心,基 ...

  5. Nginx搭建部署Web服务器并与NFS结合搭建负载均衡服务器

    Nginx搭建部署Web服务器并与NFS结合搭建负载均衡服务器 一.搭建NginxWeb服务器     此种方式是用yum安装Nginx,为保证安装成功需在安装之前提前安装epel扩展源.     用 ...

  6. Ubuntu+Django+Nginx+uWSGI+Mysql搭建Python Web服务器

    Ubuntu+Django+Nginx+uWSGI+Mysql搭建Python Web服务器 闲着无聊的时候部署了一个Django项目玩,用vm虚拟机部署的. 准备工作 我使用的系统是Ubuntu16 ...

  7. 【入门篇】Nginx + FastCGI 程序(C/C++) 搭建高性能web service的Demo及部署发布

    http://blog.csdn.net/allenlinrui/article/details/19419721 分类: C/C++2014-02-18 17:58 3875人阅读 评论(0) 收藏 ...

  8. 从0开始搭建坚不可摧的Web系统主流架构

    从0开始搭建坚不可摧的Web系统主流架构 转自:http://mp.weixin.qq.com/s/HKqgdR0qM3FhdGWcWnlpug 主题简介: 1.网站系统架构当前现状 2.Web系统主 ...

  9. 高并发系统搭建:web负载均衡

    高并发系统搭建:web负载均衡 所谓的负载均衡就是让多个请求尽量均衡的分配到不同的机器上面去 1. HTTP负载均衡 当用户的请求发来之后,web服务器通过修改HTTP响应报头中的Location标记 ...

最新文章

  1. LINUX系统中进程如何管理控制(一)
  2. 洛谷—— P1605 迷宫
  3. EasyUI框架入门学习
  4. 剑指offer(Java实现) 求1+2+3+…+n
  5. python两数交换 函数_Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?...
  6. XCTF(攻防世界)—进阶web题Write Up(二)
  7. 点云平面提取_基于LiDAR点云数据滤波方法
  8. Java操作数据库详解
  9. 转:Socket编程知识必学
  10. 【镜像更新】Windows Server 2016 数据中心版
  11. 27_多易教育之《yiee数据运营系统》数据治理-atlas部署使用篇
  12. ubuntu前置耳机孔没声音的解决办法
  13. ARP表项的创建与更新
  14. flash builder 4.6 mac 版破解方法
  15. word中如何设置页码从任意页开始
  16. 歌曲影视随意赏计算机课件,世界影视音乐赏析课件.ppt
  17. C语言 查找书籍(结构体)
  18. Ubuntu 14.04 LTS 安装配置搜狗拼音输入法
  19. HDMI的HDCP是怎么工作的?
  20. .什么是ECharts

热门文章

  1. 门禁系统服务器是指什么设备,浅述门禁系统服务器相关要点
  2. pox.xml常用依赖
  3. [负荷预测]基于线性回归模型的中长期电力负荷预测
  4. java反序列化流建立失败_关于java:处理dubbo反序列化失败的坑
  5. 新书的各种购买方式汇总【人人都是产品经理:9082】
  6. CoppeliaSim笔记(2):运动学功能(kinematics functionality)
  7. 惯性导航在石油测井中的应用
  8. WebRTC的C/C++ API
  9. 面试算法题刷题资源库
  10. 【毕业设计】基于springboot+百度AI的人脸考勤系统