部署代码使构建有时不稳定

时间:2018-07-12 13:31:13

标签: ruby-on-rails capistrano puma

所以我有一个使用puma Web服务器的ROR项目。有时,当代码被部署时(平台上有许多活动用户),这使我的构建不稳定,通过不稳定,我的意思是它在诸如undefined method to_sym' for nil:NilClassNoMethodError: undefined method -@' for nil:NilClass之类的怪异地方抛出了完全随机的错误。当我重新部署代码时,错误会消失。

  • 堆栈:ROR
  • 网络服务器:Puma(2个工人和12个线程)
  • 用于代码部署:capistrano
  • nginx在同一服务器上
  • 一台Ununtu服务器

部署脚本

            lock '3.5.0'
            set :scm, :git
            set :keep_releases, 5
            set :user,            'ubuntu'
            set :puma_threads,    [2, 12]
            set :puma_workers,    Proc.new { fetch(:stage) == "production" ? 2 : 1 }
            set :pty,             false
            set :use_sudo,        true
            set :rails_env,       Proc.new { fetch :stage }
            set :deploy_via,      :remote_cache
            set :deploy_to,       "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
            set :puma_bind,       "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
            set :puma_state,      "#{shared_path}/tmp/pids/puma.state"
            set :puma_pid,        "#{shared_path}/tmp/pids/puma.pid"
            set :puma_access_log, "#{shared_path}/log/puma.error.log"
            set :puma_error_log,  "#{shared_path}/log/puma.access.log"
            set :puma_preload_app, true
            set :puma_conf,       "#{release_path}/config/puma.rb"
            set :puma_worker_timeout, nil
            set :puma_init_active_record, true  # Change to false when not using ActiveRecord
            set :ssh_options,     { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/role.pem) }
            set :primary_server,  "35.154.8.144"
            set :jenkins_user,    "role"
            set :jenkins_token,   "29f3b5fb3862b427429f04d5cef8732b"
            set :cron_file,       "/var/spool/cron/crontabs/ubuntu"
            set :sidekiq_role, :sidekiq  
            set :sidekiq_config, "#{release_path}/config/sidekiq.yml"  
            set :sidekiq_env, Proc.new { fetch :stage }  
            set :sidekiq_log => File.join(shared_path, 'log', 'sidekiq.log')
            set :rollbar_token, 'e1e66e1a03274620b05b9e69f5776587'
            set :rollbar_env, Proc.new { fetch :stage }
            set :rollbar_role, Proc.new { :app }
            set :sqs_polling_pid, Proc.new { "#{shared_path}/tmp/pids/sqs_polling.pid" }
            set :test_log, Proc.new { "log/capistrano.test.log" }
            set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }
            set :whenever_path,       ->{ current_path }
            set :whenever_roles,      ->{ :cron }
            set :linked_dirs,  %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/source-maps public/attachments attachments config/settings config/cron}

            namespace :puma do
              desc 'Create Directories for Puma Pids and Socket'
              task :make_dirs do
                on roles(:all) do
                  execute "mkdir #{shared_path}/tmp/sockets -p"
                  execute "mkdir #{shared_path}/tmp/pids -p"
                end
              end

              before :start, :make_dirs
            end

            namespace :sqs_polling do
              desc 'Stop sqs_polling ghost processes'
              task :clean do
                on roles :sqs_polling do
                  execute "pkill -f sqs_polling_app > /dev/null 2>&1"
                end
              end

              desc 'Stop sqs_polling'
              task :stop do
                on roles(:sqs_polling) do
                  within current_path do
                    execute "if [ -d #{current_path} ] && [ -f #{fetch(:sqs_polling_pid)} ] && kill `cat #{fetch(:sqs_polling_pid)}` > /dev/null 2>&1; then rm #{fetch(:sqs_polling_pid)} ; else echo 'sqs_polling is not running'; fi"
                  end
                end
              end

              desc 'Start sqs_polling'
              task :start do
                on roles(:sqs_polling) do
                  within current_path do
                    with rails_env: fetch(:stage) do
                      execute :bundle, "exec rails runner lib/sqs_polling_app.rb >> #{current_path}/log/sqs_polling.log 2>&1 & echo $! > #{fetch(:sqs_polling_pid)}", pty: false
                      execute "ps aux | grep 'sqs_polling_app'"
                    end
                  end
                end
              end

              desc 'Restart sqs_polling'
              task :restart do
                on roles(:sqs_polling) do
                  invoke 'sqs_polling:stop'
                  invoke 'sqs_polling:start'
                end
              end
            end

            namespace :deploy do
              desc "Runs test before deploying, can't deploy unless they pass"
              task :run_tests do
                puts "--> Running tests, please wait ..."
                unless system "bundle exec rspec spec > #{fetch(:test_log)} 2>&1" #' > /dev/null'
                  system "cat #{fetch(:test_log)}"
                  exit
                else      
                  puts "--> Tests passed"
                  system "rm #{fetch(:test_log)}"
                end
              end

              task :seed do
               puts "\n=== Seeding Database ===\n"
               on roles(:backend) do
                within current_path do
                  with rails_env: fetch(:stage) do
                    execute :rake, 'db:seed'
                  end
                end
               end
              end

              task :rake do
               on roles(:backend) do
                within current_path do
                  with rails_env: fetch(:stage) do
                    execute :rake, "#{ENV["task"]}"
                  end
                end
               end
              end

              desc "Make sure local git is in sync with remote."
              task :check_revision do
                on roles(:all) do
                  if fetch(:stage) == :production
                    unless `git rev-parse HEAD` == `git rev-parse origin/master`
                      puts "WARNING: HEAD is not the same as origin/master"
                      puts "Run `git push` to sync changes."
                      exit
                    end
                  end
                end
              end

              task :nginx_restart do
                on roles(:role) do
                  if fetch(:rails_env) == :staging
                    execute "sudo ln -nfs '/home/ubuntu/apps/dashboard/current/config/nginx.staging.conf' '/etc/nginx/sites-enabled/dashboard'"
                    execute "sudo service nginx restart"
                  else
                    execute "sudo ln -nfs '/home/ubuntu/apps/dashboard/current/config/nginx.role.conf' '/etc/nginx/sites-enabled/dashboard'"
                    execute "sudo service nginx restart"
                  end
                end
              end

              task :config_files do
                on roles(:all) do
                  within current_path do
                    execute "sudo scp -i #{fetch(:ssh_options)[:keys].first} ubuntu@#{fetch(:primary_server)}:/home/ubuntu/aws/settings/#{fetch(:rails_env)}.yml /home/ubuntu/apps/dashboard/shared/config/settings/#{fetch(:rails_env)}.yml"
                  end
                end

              end

              task :copy_to_s3 do
                on roles(:app) do
                  within release_path do
                    with rails_env: fetch(:rails_env) do
                      execute :rake, "s3:sync"
                    end
                  end 
                end
              end

              task :source_map_to_rollbar do
                on roles(:app) do
                  within release_path do
                    with rails_env: fetch(:rails_env) do
                      execute :rake, "s3:source_map_to_rollbar"
                    end
                  end 
                end
              end

              task :clean_assets do
                on roles(:all) do
                  within current_path do
                    with rails_env: fetch(:rails_env) do
                      execute :rake, "assets:clean[5]"
                    end
                  end 
                end
              end


              desc 'Initial Deploy'
              task :initial do
                on roles(:sqs_polling) do
                  invoke 'sqs_polling:clean'
                end
                on roles(:app) do
                  before 'deploy:restart', 'puma:start'
                  invoke 'deploy'
                end
              end

              desc 'Restart application'
              task :restart do
                on roles(:sqs_polling), in: :sequence, wait: 5 do
                  invoke 'sqs_polling:restart'
                end
                on roles(:app), in: :sequence, wait: 5 do
                  within release_path do
                    with rails_env: fetch(:rails_env) do
                      execute :rake, "s3:deployed"
                      invoke 'puma:restart'
                      invoke 'sqs_polling:restart'
                    end
                  end 
                end
              end


              before :clean_assets,   :config_files
              after  :config_files,   :nginx_restart
              before :starting,       :check_revision
              after  :finishing,      :compile_assets
              before :compile_assets, :clean_assets
              after  :compile_assets, :copy_to_s3
              after  :copy_to_s3,     :source_map_to_rollbar
              after  :finishing,      :cleanup
              after  :finishing,      :restart
            end

0 个答案:

没有答案