我們剛剛從乘客轉移到獨角獸主持幾個rails應用程序。 一切都很好,但我們通過New Relic注意到請求在100到300毫秒之間排隊。獨角獸請求排隊
以下是圖表:
我不知道在哪裏,這是從這裏來的是我們獨角獸的conf:
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;
}
我們不是在重負載下,所以我不明白爲什麼請求被阻塞在隊列中。 按照獨角獸的規定,我們有6名獨角獸工人。
任何想法可能來自哪裏?
乾杯
編輯:每分鐘
平均請求:約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個虛擬核心,5個EC2計算單元)
我們承載4個rails應用程序,這個應用程序有6個工作人員,我們有一個4個,一個2個,另一個1個。自從我們遷移到獨角獸以來,他們都遇到了請求排隊。 我不知道乘客是否在作弊,但New Relic在我們使用它時沒有記錄任何請求排隊。我們還有一個node.js應用程序處理文件上傳,一個mysql數據庫和2個redis。
編輯3:
我們使用紅寶石1.9.2p290,nginx的1.0.10,麒麟4.2.1和3.3.3 newrelic_rpm。 我會嘗試沒有newrelic明天,並會讓你知道這裏的結果,但對於我們使用乘客與新文物,相同版本的紅寶石和nginx的信息,並沒有任何問題。
編輯4:
我試圖增加client_body_buffer_size
和proxy_buffers
與
client_body_buffer_size 256k;
proxy_buffers 8 256k;
但它並沒有這樣的伎倆。
編輯5:
我們終於找到它了... ...擊鼓聲的 冠軍是我們的SSL暗號。當我們將其更改爲RC4時,我們看到請求排隊從100-300ms降至30-100ms。
是您的實際響應時間增加了,當你使用汽車,或者是它只是什麼負責響應時間New Relic的擊穿該令人震驚? – 2012-03-31 17:27:58
當我們使用乘客時,我們在大約120ms內提供了請求,所以是平均請求時間令人震驚。我的主要問題是,爲什麼當我們每分鐘沒有請求6名獨角獸工作人員的請求時,這些請求陷入隊列中? – Mike 2012-03-31 23:27:16
負載是多少?多少RPM?你有沒有做數學(你的6名工人能否跟上負荷)?你有沒有嘗試產卵更多的獨角獸工作者? – 2012-04-01 22:27:18