очередь запросов единорога

Мы только что перешли с пассажира на единорога, чтобы разместить несколько приложений для рельсов. Все работает отлично, но через New Relic мы заметили, что запросы стоят в очереди от 100 до 300 мс.

Вот график:

enter image description here

Я понятия не имею, откуда это взялось, вот наша конференция единорогов:

current_path = '/data/actor/current'
shared_path = '/data/actor/shared'
shared_bundler_gems_path = "/data/actor/shared/bundled_gems"
working_directory '/data/actor/current/'

worker_processes 6

listen '/var/run/engineyard/unicorn_actor.sock', :backlog => 1024

timeout 60

pid "/var/run/engineyard/unicorn_actor.pid"

logger Logger.new("log/unicorn.log")

stderr_path "log/unicorn.stderr.log"
stdout_path "log/unicorn.stdout.log"

preload_app true

if GC.respond_to?(:copy_on_write_friendly=)
  GC.copy_on_write_friendly = true
end

before_fork do |server, worker|
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.connection.disconnect!
  end

  old_pid = "#{server.config[:pid]}.oldbin"

  if File.exists?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :TERM : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
  sleep 1
end

if defined?(Bundler.settings)
  before_exec do |server|
    paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
    paths.unshift "#{shared_bundler_gems_path}/bin"
    ENV["PATH"] = paths.uniq.join(File::PATH_SEPARATOR)

    ENV['GEM_HOME'] = ENV['GEM_PATH'] = shared_bundler_gems_path
    ENV['BUNDLE_GEMFILE'] = "#{current_path}/Gemfile"
  end
end

after_fork do |server, worker|
  worker_pid = File.join(File.dirname(server.config[:pid]), "unicorn_worker_actor_#{worker.nr$
  File.open(worker_pid, "w") { |f| f.puts Process.pid }
  if defined?(ActiveRecord::Base)
    ActiveRecord::Base.establish_connection
  end

end

наш nginx.conf:

user deploy deploy;
worker_processes 6;

worker_rlimit_nofile 10240;
pid /var/run/nginx.pid;

events {
  worker_connections 8192;
  use epoll;
}

http {

  include /etc/nginx/mime.types;

  default_type application/octet-stream;

  log_format main '$remote_addr - $remote_user [$time_local] '
                  '"$request" $status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

  sendfile on;

  tcp_nopush        on;

  server_names_hash_bucket_size  128;

  if_modified_since before;
  gzip              on;
  gzip_http_version 1.0;
  gzip_comp_level   2;
  gzip_proxied      any;
  gzip_buffers      16 8k;
  gzip_types        application/json text/plain text/html text/css application/x-javascript t$
  # gzip_disable      "MSIE [1-6]\.(?!.*SV1)";

  # Allow custom settings to be added to the http block
  include /etc/nginx/http-custom.conf;
  include /etc/nginx/stack.conf;
  include /etc/nginx/servers/*.conf;
}

и наша конфигурация nginx для конкретного приложения:

upstream upstream_actor_ssl {
  server unix:/var/run/engineyard/unicorn_actor.sock fail_timeout=0;
}

server {
  listen 443;

  server_name letitcast.com;

  ssl on;
  ssl_certificate /etc/nginx/ssl/letitcast.crt;
  ssl_certificate_key /etc/nginx/ssl/letitcast.key;
  ssl_session_cache shared:SSL:10m;

  client_max_body_size 100M;

  root /data/actor/current/public;

  access_log /var/log/engineyard/nginx/actor.access.log main;
  error_log /var/log/engineyard/nginx/actor.error.log notice;

  location @app_actor {
    include /etc/nginx/common/proxy.conf;
    proxy_pass http://upstream_actor_ssl;
  }

  include /etc/nginx/servers/actor/custom.conf;
  include /etc/nginx/servers/actor/custom.ssl.conf;

  if ($request_filename ~* \.(css|jpg|gif|png)$) {
    break;
  }

  location ~ ^/(images|javascripts|stylesheets)/ {
    expires 10y;
  }

  error_page 404 /404.html;
  error_page 500 502 504 /500.html;
  error_page 503 /system/maintenance.html;

  location = /system/maintenance.html { }

  location / {
    if (-f $document_root/system/maintenance.html) { return 503; }

    try_files  $uri $uri/index.html $uri.html @app_actor;
  }

  include /etc/nginx/servers/actor/custom.locations.conf;
}

У нас нет большой нагрузки, поэтому я не понимаю, почему запросы зависают в очереди. Как указано в конфиге единорога, у нас есть 6 рабочих-единорогов.

Любая идея, откуда это может исходить?

Привет

РЕДАКТИРОВАТЬ:

Среднее количество запросов в минуту :около 15 в большинстве случаев, более 300 при просмотре, но с момента миграции мы не получали ни одного запроса.
Средняя загрузка ЦП :0,2 -0,3

Пробовал с 8 рабочими, ничего не изменилось.

Я также использовал капли дождя , чтобы посмотреть, чем заняты рабочие-единороги.

Вот рубиновый скрипт:

#!/usr/bin/ruby

# this is used to show or watch the number of active and queued
# connections on any listener socket from the command line

require 'raindrops'
require 'optparse'
require 'ipaddr'
usage = "Usage: #$0 [-d delay] ADDR..."
ARGV.size > 0 or abort usage
delay = false

# "normal" exits when driven on the command-line
trap(:INT) { exit 130 }
trap(:PIPE) { exit 0 }

opts = OptionParser.new('', 24, '  ') do |opts|
  opts.banner = usage
  opts.on('-d', '--delay=delay') { |nr| delay = nr.to_i }
  opts.parse! ARGV
end

socks = []
ARGV.each do |f|
  if !File.exists?(f)
    puts "#{f} not found"
    next
  end

  if !File.socket?(f)
    puts "#{f} ain't a socket"
    next
  end

  socks << f
end

fmt = "% -50s % 10u % 10u\n"
printf fmt.tr('u','s'), *%w(address active queued)

begin
  stats = Raindrops::Linux.unix_listener_stats(socks)
  stats.each do |addr,stats| 
    if stats.queued.to_i > 0
      printf fmt, addr, stats.active, stats.queued
    end
  end
end while delay && sleep(delay)

Как я это запустил:

./linux-tcp-listener-stats.rb -d 0.1 /var/run/engineyard/unicorn_actor.sock

Таким образом, он в основном проверяет каждую 1/10 с, есть ли запросы в очереди и есть ли они на выходе:

розетка | количество обрабатываемых запросов | количество запросов в очереди

Вот суть результата:

https://gist.github.com/f9c9e5209fbbfc611cb1

РЕДАКТИРОВАТЬ2:

Вчера вечером я попытался уменьшить количество рабочих nginx до одного, но это ничего не изменило.

Для информации, мы размещены на Engine Yard и имеем экземпляр High -CPU Medium 1,7 ГБ памяти, 5 вычислительных блоков EC2 (2 виртуальных ядра с 2,5 вычислительными блоками EC2 в каждом )

. Мы размещаем 4 приложения rails, у этого есть 6 рабочих, у нас есть один с 4, один с 2 и еще один с одним. Все они столкнулись с очередями запросов с тех пор, как мы перешли на unicorn. Я не знаю, обманывал ли Passenger, но New Relic не регистрировал очереди запросов, когда мы его использовали. У нас также есть приложение node.js, обрабатывающее загрузку файлов, база данных mysql и 2 redis.

РЕДАКТИРОВАТЬ 3:

Мы используем ruby ​​1.9.2p290, nginx 1.0.10, unicorn 4.2.1 и newrelic _rpm 3.3.3. Завтра я попробую без newrelic и сообщу вам о результатах здесь, но для информации мы использовали пассажира с новой реликвией, ту же версию ruby ​​и nginx, и у нас не было никаких проблем.

РЕДАКТИРОВАТЬ 4:

Я попытался увеличить client_body_buffer_sizeи proxy_buffersс помощью

client_body_buffer_size 256k;
proxy_buffers 8 256k;

. Но это не сработало.

РЕДАКТИРОВАТЬ 5:

Разобрались наконец...барабанная дробь... Победителем стал наш шифр SSL. Когда мы изменили его на RC4, мы увидели, что очередь запросов сократилась со 100 -300 мс до 30 -100 мс.

23
задан Mike 21 March 2013 в 17:57
поделиться