【发布时间】:2012-04-14 14:53:11
【问题描述】:
我们刚刚从乘客迁移到独角兽,以托管几个 Rails 应用程序。 一切正常,但我们通过 New Relic 注意到请求排队的时间在 100 到 300 毫秒之间。
这是图表:
我不知道这是从哪里来的,这是我们的独角兽会议:
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 conf:
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;
}
我们的负载并不重,所以我不明白为什么请求会卡在队列中。 按照 unicorn conf 中的规定,我们有 6 个 unicorn 工人。
知道这可能来自哪里吗?
干杯
编辑:
每分钟的平均请求数:大部分时间约为 15 个,偷看次数超过 300 个,但自迁移以来我们没有遇到过。
CPU平均负载:0.2-0.3
我尝试了 8 个工人,但没有任何改变。
我还使用raindrops 来查看独角兽工人在做什么。
这是 ruby 脚本:
#!/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
EDIT2:
我昨晚尝试将 nginx 工作人员的数量减少到一个,但没有任何改变。
有关信息,我们托管在 Engine Yard 上,并拥有一个高 CPU 中型实例 1.7 GB 内存、5 个 EC2 计算单元(2 个虚拟内核,每个内核有 2.5 个 EC2 计算单元)
我们托管 4 个 rails 应用程序,这个有 6 个 worker,一个有 4 个,一个有 2 个,另一个有一个。自从我们迁移到独角兽后,他们都在经历请求排队。 我不知道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,并会在这里告诉您结果,但对于我们使用带有 new relic 的乘客的信息,相同版本的 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 毫秒。
【问题讨论】:
-
您的实际响应时间是否比您使用Passenger 时增加了,还是仅仅是New Relic 对响应时间的原因进行了细分?
-
@sarnold:独角兽肯定不慢。在我的应用程序中,15 名工作人员以亚毫秒级的响应时间处理 10-30k rpm。
-
@Mike 注意here 和here 关于慢速客户端的警告:
If your application responses are larger than the socket buffer or if you’re handling large requests (uploads), worker processes will also be bottlenecked by the speed of the client connection. You should not allow unicorn to serve clients outside of your local network.据我了解,这将显着影响您的性能测试。如果这是有用的信息,我会重写它作为答案。 -
@MrGomez 这就是我们使用 nginx 的原因,我们不通过 unicorn 处理大型上传(我们使用的是节点)。
-
@Mike 你知道发生了什么吗?我在使用独角兽的请求队列中看到了类似的时间......
标签: ruby-on-rails nginx passenger unicorn